happymasssacre happymasssacre - 2 months ago 23
C Question

sprintf to copy int into string in C

I'm trying to convert an integer to string using

sprintf
but it's not working as expected.

When I input a number it works fine, I can show the number on screen. But if I input a string it always shows
"2"
on screen.

I was planning to get the string so that I can check if it's a number or not with the
isdigit()
function.

Tried
itoa()
too but it was pretty much the same story.

int main()
{
int num;
char string[31];

printf("Number: ");
scanf("%d",&num);

sprintf(string, "%d", num);

printf("%s", string);
return 0;
}


If I input
2999
: it shows
"2999"


If I input
"dog"
: it shows
"2"


How can I get that string? For what I've seen it should work, perhaps something's up with my IDE? I have Code Blocks 16.01.

Answer

int num; leaves num uninitialized. When you input "dog", the scanf operation doesn't match anything against num, so nothing is stored in it. Thus when you printf num it is still uninitialized and the value you get is garbage.

You could test for this by examining the return of scanf. scanf will return the number of successful matches, which you should expect to be 1 if a number was entered

printf("Number: ");
if (scanf("%d",&num) != 1) {
    puts("You didn't enter a number!");
}

For a better proof it is not being set, try initializing num to something and see what gets printed

#include <stdio.h>
int main() {
  int num = 5; // I'm initializing to 5
  char string[31];

  printf("Number: ");
  scanf("%d",&num);

  sprintf(string, "%d", num);

  printf("%s", string);  // now this prints "5" if I input "dog"
  return 0;
}

For further evidence of this, running your original program through valgrind prints a bunch of errors about using an uninitialized value. I've edited out some of the noise in the below:

$ echo "dog" | valgrind ./a.out
==32450== 
==32450== Use of uninitialised value of size 8
==32450==    at _itoa_word
==32450==    by vfprintf 
==32450==    by vsprintf
==32450==    by  sprintf
==32450==    by main
==32450== 
==32450== Conditional jump or move depends on uninitialised value(s)
==32450==    at vfprintf 
==32450==    by vsprintf
==32450==    by sprintf
==32450==    by main

To accomplish your goal of reading a string then checking it, you'll want to use fgets instead

#include <stdio.h>
#include <ctype.h>

int main() {
  char input[31];
  printf("Number: ");
  fgets(input, sizeof input, stdin);  // read up to a line of input as a string
  if (isdigit(input[0])) {  // check if it's a number
    puts("this is a number (or at least starts with one)");
  } else {
    puts("this is not a number");
    return 1;
  }

  int num = 0;
  char string[31];

  sscanf(input, "%d", &num);  // now you can do the scanf on the input string

  sprintf(string, "%d", num);
  printf("%s", string);
  return 0;
}