happymasssacre
happymasssacre

Reputation: 23

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.

Upvotes: 2

Views: 5160

Answers (2)

Ryan Haining
Ryan Haining

Reputation: 36872

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;
}

Upvotes: 1

D.Shawley
D.Shawley

Reputation: 59573

I recommend looking at the return value from scanf. It is likely returning zero. It is failing and not storing a value in num. The 2 is likely the indeterminate value that was on the stack when the program started.

If you want to read the value that was input, then use fgets to read the input into the buffer and then sscanf to extract it.

Upvotes: 1

Related Questions