0

I have this code and I need help converting the comments to c code

// if the input of scanf() is "q"
{
   break;
}
else
{
   // convert to int
}

Firstly, how do I check if an input is a certain character. Secondly, how do I turn a string into an integer. Example: "123" -> 123

Things I've tried, that didn't work: (it is possible that I implemented these solutions incorrectly)

Oskar
  • 119
  • 8
  • 2
    (1) [Do not use `scanf`](https://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html). (2) Learn about [the way to compare strings in C](https://stackoverflow.com/questions/8004237/how-do-i-properly-compare-strings-in-c). (3) Learn how to [convert a string to a number with error detection](https://stackoverflow.com/questions/14176123/correct-usage-of-strtol) (including detection of non-numbers and range errors). – n. m. could be an AI Aug 29 '22 at 07:49
  • Don't try to use `scanf` for interactive input. Use it only for quick and dirty test programs. – Jabberwocky Aug 29 '22 at 08:43
  • 1
    One possibility is to read input as integers using `%d`, and quit when `scanf` fails. That will quit if the user types "q", although also if the user types "x", or "done", or anything non-numeric. Checking `scanf`'s return value is an excellent idea anyway. – Steve Summit Aug 29 '22 at 11:00

5 Answers5

1

I am not using any standard libraries except for stdio.h to print some logging information on the window

you have to know also that any string is terminated by null character which is '\0' to indicate the termination of the string , also you have to check is the user entered characters not numbers and so on (that's not implemented in this code).

I also handled if negative numbers are entered.

but you have to handle if the user entered decimals numbers , to sum up . there are so many cases to handle.

and here the edited code :

#include <stdio.h>

int main(){
    char inputString[100];

    printf("enter the input:\n");
    scanf("%s", &inputString);

    if(inputString[0] == 'q' && inputString[1] == '\0' )
    {
        printf("quiting\n");
        //break;
    }
    else {
        int i = 0;
        int isNegative = 0;
        int number = 0;

        // check if the number is negative
        if (inputString[0] == '-') {
            isNegative = 1;
            i = 1;
        }
        // convert to int
        for ( ;inputString[i] != '\0' ; i++) {
            number *= 10;
            number += (inputString[i] - '0');
        }
        if(isNegative == 1)
            number *= -1;

        printf("you entered %d\n", number);
    }
    return 0;
}
abdo Salm
  • 1,678
  • 4
  • 12
  • 22
1

Here are some guidelines:

  • scanf("%s", &var) is incorrect: you should pass the maximum number of characters to store into the array var and pass the array without the & as it will automatically convert to a pointer to its first element when passed as an argument:

      char var[100];
      if (scanf("%99s", var) != 1) {
          printf("premature end of file\n"); 
          return 1;
      }
    
  • to compare the string read to "q", you can use strcmp() declared in <string.h>:

      if (strcmp(var, "q") == 0) {
          printf("quitting\n"); 
          return 0;
      }
    
  • to convert the string to the number it represents, use strtol() declared in <stdlib.h>:

      char *p;
      long value = strtol(var, &p, 0);
    
  • testing for a proper conversion is tricky: strtol() updated p to point to the character after the number and set errno in case of range error:

      errno = 0;
      char *p;
      long value = strtol(var, &p, 0);
      if (p == var) {
          printf("not a number: %s\n", p); 
          return 1;
      }
      if (*p != '\0') {
          printf("extra characters: %s\n", p); 
          return 1;
      }
      if (errno) {
          printf("conversion error: %s\n", strerror(errno));
          return 1;
      }
      printf("the number entered is: %ld\n", value);
      return 0;
    

Here is a complete program:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>          
#include <string.h>

int main() {
    char var[100];
    char *p;
    long value;

    printf("Enter a number: ");
    if (scanf("%99s", var) != 1) {
        printf("premature end of file\n"); 
        return 1;
    }

    if (strcmp(var, "q") == 0) {
        printf("quitting\n"); 
        return 0;
    }

    errno = 0;
    value = strtol(var, &p, 0);
    if (p == var) {
        printf("not a number: %s\n", p); 
        return 1;
    }
    if (*p != '\0') {
        printf("extra characters: %s\n", p); 
        return 1;
    }
    if (errno) {
        printf("conversion error: %s\n", strerror(errno));
        return 1;
    }
    printf("the number entered is: %ld\n", value);
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
1

The fundamental question here is, Do you want to use scanf?

scanf is everyone's favorite library function for easily reading in values. scanf has an input specifier, %d, for reading in integers. And it has a different input specifier, %s, for reading in arbitrary strings. But scanf does not have any single input specifier that means, "Read in an integer as an integer if the user types a valid integer, but if the user types something like "q", have a way so I can get my hands on that string instead."

Unless you want to move mountains and implement your own general-purpose input library from scratch, I think you have basically three options:

  1. Use scanf with %d to read integers as integers, but check scanf's return value, and if scanf fails to read an integer, use that failure to terminate input.
  2. Use scanf with %s to read the user's input as a string, so you can then explicitly test if it's a "q" or not. If not, convert it to an integer by hand. (More on this below.)
  3. Don't use scanf at all. Use fgets to read the user's input as a whole line of text. Then see if it's a "q" or not. If not, convert it to an integer by hand.

Number 1 looks something like this:

while(some loop condition) {
    printf("enter next integer, or 'q' to quit:\n");
    if(scanf("%d", &i) != 1) {
        /* end of input detected */
        break;
    }

    do something with i value just read;
}

The only problem with this solution is that it won't just stop if the user types "q", as your original problem statement stipulated. It will also stop if the user types "x", or "hello", or control-D, or anything else that's not a valid integer. But that's also a good thing, in that your loop won't get confused if the user types something unexpected, that's neither "q" nor a valid integer.

My point is that explicitly checking scanf's return value like this is an excellent idea, in any program that uses scanf. You should always check to see that scanf succeeded, and do something different if it fails.

Number 2 would look something like this:

char tmpstr[20];

while(some loop condition) {
    printf("enter next integer, or 'q' to quit:\n");
    if(scanf("%19s", tmpstr) != 1) {
        printf("input error\n");
        exit(1);
    }

    if(strcmp(tmpstr, "q") == 0) {
        /* end of input detected */
        break;
    }

    i = atoi(tmpstr);    /* convert string to integer */

    do something with i value just read;
}

This will work well enough, although since it uses atoi it will have certain problems if the user types something other than "q" or a valid integer. (More on this below.)

Number 3 might look like this:

char tmpstr[20];

while(some loop condition) {
    printf("enter next integer, or 'q' to quit:\n");
    if(fgets(tmpstr, 20, stdin) == NULL) {
        printf("input error\n");
        exit(1);
    }

    if(strcmp(tmpstr, "q\n") == 0) {
        /* end of input detected */
        break;
    }

    i = atoi(tmpstr);    /* convert string to integer */

    do something with i value just read;
}

One thing to note here is that fgets includes the newline that the user typed in the string it returns, so if the user types "q" followed by the Enter key, you'll get a string back of "q\n", not just "q". You can take care of that either by explicitly looking for the string "q\n", which is kind of lame (although it's what I've done here), or by stripping the newline back off.

Finally, for both #2 and #3, there's the question of, what's the right way to convert the user's string to an integer, and what if it wasn't a valid integer? The easiest way to make the conversion is to call atoi, as my examples so far have shown, but it has the problem that its behavior on invalid input is undefined. In practice, it will usually (a) ignore trailing nonnumeric input and (b) if there's no numeric input at all, return 0. (That is, it will read "123x" as 123, and "xyz" as 0.) But this behavior is not guaranteed, so these days, most experts recommend not using atoi.

The recommended alternative is strtol, which looks like this:

char *endp;
i = strtol(tmpstr, &endp, 10);    /* convert string to integer */

Unlike atoi, strtol has guaranteed behavior on invalid input. Among other things, after it returns, it leaves your auxiliary pointer endp pointing at the first character in the string it didn't use, which is one way you can determine whether the input was fully valid or not. Unfortunately, properly dealing with all of the ways the input might be invalid (including trailing garbage, leading garbage, and numbers too big to convert) is a surprisingly complicated challenge, which I am not going to belabor this answer with.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
0

You can try this: (Assuming only positive integers needs to convert)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    // Write C code here
    char var[100];
    int numb_flag=1, i=0,number=0;
    
    scanf("%s",var);
    
    while(var[i]!='\0') { // Checking if the input is number
        if(var[i]>=48 && var[i]<=57)
            i++;    
        else {
            numb_flag = 0;
            break;
        }
    }
    if(numb_flag==1) {
        number = atoi(var);
        printf("\nNumber: %d",number);
    } else {
        printf("\nNot A Number");
    }
    
    return 0;
}
sat
  • 91
  • 8
0
//Mind that in order to be more precise you could also use atof(). 
//The function works the same way as atoi() but is able to convert float
// (returned value is 'double') the string s

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXILEN 100 /*change the value based on your needs*/

int main(){
    int n, lim = MAXILEN;
    char s[MAXILEN], *p = s, c;

    /*taking the string from the input -- I do not use scanf*/
    while(--lim > 0 && (c = getchar()) != EOF && c != '\n')
        *p++ = c;
    //here you can also do the check (if you want the '\n' char):
    //if(c == '\n')
    //  *s++ = c; 
    *p = '\0';

    if(s[0] == 'q' && s[1] == '\0') 
        exit(EXIT_SUCCESS); /*change the argument based on your needs*/
    else
        n = atoi(s);

    printf("[DEBUG]: %d\n", n);
}