C Programming Input Error - c

int main(void) {
char *input;
printf("prompt>");
scanf("%s", input);
printf("%s", input);
return 0;
}
prompt>input
RUN FAILED (exit value 138, total time: 3s)
What's wrong with the code? Has to be either the scanf() or the second printf(). The input is of unknown length. A lot people have said to simply create a char array of length 'X' to hold the input. Just wanted to know then why this code works.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
/* prompt */
char input;
printf("prompt>");
scanf("%s", &input);
printf("%s", &input);
return 0;
}

Your specific problem is that you have no storage behind input. It's an uninitialised pointer, pointing to a random spot in memory, which is unlikely to be anywhere useful.
You can use something like:
char *input = malloc (100);
// check that input != NULL
// use it
free (input);
or:
char input[100];
but you have a serious problem with your use of scanf (see below).
You should never use an unbounded %s in scanf (or any of its variants unless you totally control the input). It's a dangerous practice prone to buffer overflows and the sooner you get out of the habit, the better. It's akin to gets() in that way.
From an earlier answer of mine, this piece of code below (along with your main code incorporated into it) provides a safe way of getting user input. You pass in an optional prompt, the buffer to load the input into, and the size of the buffer.
It will return the input up to the size of the buffer (stripped of the newline if there) then clear out the rest of the line if necessary so that it doesn't affect the next input operation. It will return either OK or an error indication on end-of-file or if the input was too long (you still get the first part of the input in case you want to do something with it).
Once you have the line, you can sscanf it, safely, to your heart's content. However, that's not required in your case since you're only trying to get a string. Just use the buffer that's returned directly.
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
int main(void) {
char input[10];
int rc = getLine ("prompt> ", input, sizeof (input));
switch (rc) {
case NO_INPUT: printf ("\nNo input recieved\n"); break;
case TOO_LONG: printf ("Too long, truncated input below:\n");
default: printf("Your input was [%s]\n", input);
}
return 0;
}
Give that a shot, it's far more robust than using scanf("%s") on its own.
As for your update asking why this works:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
/* prompt */
char input;
printf("prompt>");
scanf("%s", &input);
printf("%s", &input);
return 0;
}
It's undefined code. Period. You only allocate space for a character but you scan in a string. Since a string is a character array of all the characters followed by a zero character, the only string you could input safely there would be an empty one.
Anything else will write to both the character and whatever happens to be adjacent to the character on the stack.
This is no different to allocating char input[100] then entering 200 characters, it's still buffer overflow and should be avoided.
Discussion below is based on a particular implementation of C, not necessarily all implementations.
Chances are, you got lucky here. Compilers may generate code that keeps the stack pointer aligned so that, even though you asked for one byte, you may get space allocated for four (or even more, depending on the architecture - I'll assume most types are four bytes here for simplicity).
In addition, you may find that you can also safely overwrite the eight bytes of argc integer and argv pointer (they're probably still there even though you don't use them, no point having two different sets of start-up code just to save a few bytes on the stack).
If you write further than that, you'll eventually overwrite the return address from main to your start-up code. Then you'll know about it since your code will go off into la-la land when main exits.
With undefined behaviour, anything can happen. Sometimes that anything includes the possibility that it will work perfectly (similar to "throw a deck of cards in the air often enough and they'll eventually fall in a nice neat sorted heap" but a little less random).
That does not make undefined behaviour any less of a bad thing.

char *input;
Is only a pointer - there is no data space allocated store the data that scanf collects.
try this instead
char input[100];

You may want to try scanf("%c", input) inside of a while loop that has your delimiting character. You should also make input an array char input[X] where X is a number of sufficient value to hold the most likely values for your input. I would try making input an array first though.

You forgot to allocate the memory before using your pointer.
Try it:
int main(void) {
char input[256];
printf("prompt>");
scanf("%s", input);
printf("%s", input);
return 0;
}
or even:
#include <stdlib.h>
#include <stdio.h>
int main(void) {
char *input = (char *) malloc(sizeof(char) * 256));
printf("prompt>");
scanf("%s", input);
printf("%s", input);
return 0;
}

What compiler do you use? In Turbo C 3.0 it works.
Try this variant:
#include <stdio.h>
#include <alloc.h>
int main(void)
{
char *input = (char*)calloc(100, sizeof(char));
printf("prompt>");
scanf("%s", input);
printf("%s", input);
free(input);
return 0;
}

Try:-
int main(void) {
char input[100];
printf("prompt>");
scanf("%99s", input);
printf("%s", input);
return 0;
}
This will limit the string to 99 bytes. Note "%s" == string of characters delimited by white space or newline ie. you only get the first word!
I think what you really want is:
#include <stdio.h>
int main(void) {
char input[99];
printf("prompt>");
fgets(input,99,stdin);
printf("->%s<-", input);
return 0;
}
You probably need to add some code to get rid of unwanted new line characters!

Related

How to print different strings depending on the input?

I want one message to appear if the name Emily or Jack is entered and a different message for another input.
My code:
#include <stdio.h>
#include <string.h>
int main()
{
char name;
printf("What is your name?");
gets(name);
if ((strcmp(name,"Emily") == 0) || (strcmp(name,"Jack") == 0))
{
printf("Hello %s\n", name);
} else
{
printf("Welcome Stranger!\n");
}
return 0;
}
This code will compile but won't output anything.
The first problem is that name can store exactly one char, to store a string of characters you'll need a char array.
The second problem, not causing the faulty behavior but equaly important, is the use of gets. This function was deprecated in C99 and removed from the international standard with C11, and for good reason, it's very dangerous as it can easily overflow the destination buffer, it has no control over the length of the input stream. fgets is regularly used instead.
char name[256]; //array store the name
//...
fgets(name, sizeof name, stdin); //safe, can't overflow the buffer, input size is limited
name[strcspn(name, "\n")] = '\0'; //fgets parses the newline character, it must be removed
//...

Why does gets() read in more characters to the pointer than the limit I set it when initializing it with calloc()? [duplicate]

This question already has answers here:
Why is the gets function so dangerous that it should not be used?
(13 answers)
Closed 4 years ago.
I'm trying to get a hold of dynamic memory allocation and I just want my program to get a string and the max number of characters that should be printed from the string from the user, then just output the string up to the number of characters I allocated with calloc. When I run the program, it completely disregards the limit I set for it using calloc() and just prints out the whole string.
I tried using malloc but had the same results. Also, I dereferenced text when I first tried printing out the inputted text but it caused the program to stop after you entered the string you wanted printed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int max;
char *text = NULL;
printf("\n\n");
printf("Please enter the limit for the string as a positive integer: \n");
scanf("%d", &max);
text = (char *)calloc(max, sizeof(char));
if (text != NULL)
{
printf("Please enter the string you want printed: \n");
scanf(" "); //read in next character so it pauses
gets(text);
printf("Inputted text is : %s\n", text);
}
free(text);
text = NULL;
return 0;
}
Yes, I know, I get the warning that gets is unsafe but I was watching from a tutorial and the instructor's version built and ran fine. Even if I use scanf to read in a string into text, the result it the same.
Revised code using fgets():
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int max;
char *text = NULL;
printf("\n\n");
printf("Please enter the limit for the string as a positive integer: \n");
scanf("%d", &max);
text = (char *)calloc(max, sizeof(char));
if (fgets(text, max, stdin))
{
printf("Please enter the string you want printed: \n");
fgets(text, max, stdin);
text[strcspn(text, "\n")] = '\0';
printf("Inputted text is : %s\n", text);
}
free(text);
text = NULL;
return 0;
}
I changed my code to use fgets instead and made some corrections. It returns 1 less character than the "max" the user inputs. Also, does using fgets mean I don't need to bother with calloc?
When you allocate memory and assign it to a pointer, there is no way to deduce the size of the memory from the pointer in hand. So gets has no chance (and will therefore not check) if it will exceed the amount of memory you reserved. BTW: gets is not part of C standard any more (since C11). Use fgets instead and pass your max as argument:
if (fgets(text, max, stdin)) {
// something successfully read in
text[strcspn(text, "\n")] = '\0';
}
Note that fgets, in contrast to gets, preserves any entered new line and keeps it at the end of text. To get rid of this, you can use text[strcspn(text, "\n")] = '\0', which will let the string end at the new line character (if any).
I think the exact reason your code is disregarding the max variable is that the gets() function is writing over all the null bytes in your text character array when the string provided on standard input is longer than max. This is one of the many reasons why we always say “never use gets()”!
More specifically, gets() will continue to write into your array from stdin until it reaches a newline or EOF character, with no regard to the bound of it. The fact that you’re seeing the entire string printed if just undefined behavior.

Why does my program pause after using scanf? [duplicate]

This question already has answers here:
How to read from input until newline is found using scanf()?
(7 answers)
What is the effect of trailing white space in a scanf() format string?
(4 answers)
Closed 6 years ago.
#include<stdio.h>
#include<stdlib.h>
int main()
{
char *userInput;
userInput = (char*)malloc(sizeof(userInput));
printf("Commands:\n");
printf("\ta name - adds given name to list\n");
printf("\tr name - removes given name from list\n");
printf("\tp - prints out list\n");
printf("\te - exits\n");
printf("\n\nEnter a command: ");
scanf("%s\n",userInput);
printf("\nThe user input was: %s\n", userInput);
return 0;
}
I compile the code "gcc -std=gnu99 -m32 -Wall -g -o namelist namelist.c"
whenever I run the executable all of the first printf are displayed and I get prompt on an input. Whenever I enter an input and press enter, I don't get prompt the next printf until I put another input in.
While a character (char) or set of characters (char*) are coming from stdin with scanf of similar function \n (result of Enter key pushing) remains in the buffer. So before next input the program should clean that \n as well as all other mess that can be in the input buffer (e.g. after incorrect entering numbers, such as 12asw - scanf takes 12 and leaves asw\n in the buffer).
Consider the following example and pay attention, that I recommend to use clnInpBuf():
#include <stdio.h>
void clnInpBuf()
{
char c;
while ((c = getchar()) != '\n' && c != EOF);
}
int main(void)
{
char str[10];
char ch;
scanf("%c", &ch);
fflush(stdin); // in some cases that works for input stream
// (but fflush is better to use only for output streams)
scanf("%9s", str);
clnInpBuf(); // this works always
printf("char was %c.\n", ch);
printf("string was %s.\n", str);
}
UPDATE:
template for your "command processor" can be:
int main(void)
{
char name[21];
char command;
while (1)
{
scanf("%c", &command);
clnInpBuf();
switch (command)
{
case 'a':
case 'r': scanf("%20s", name);
clnInpBuf();
printf("Command was:\n%c %s\n", command, name); // if ('a'==command) addRecord(name); else removeRecord(name);
break;
case 'p': // TODO: add output
break;
case 'e': return 0;
break; // this is not realy needed
default:
printf("Wrong command\n");
}
}
}
Just take out the "\n" in your
scanf("%s\n",userInput)
Read carefully scanf(3). Notice that with gcc -m32 you have sizeof(userInput) equal to 4 (the size of all pointers is the same; without the -m32 it would be 8). So if the user is typing something like working (or any input of four characters or more, not just one letter like a), you have undefined behavior (because of a buffer overflow) and that is really bad. You probably should consider using getline(3) instead (or perhaps even readline(3)), e.g.
char* userInput=NULL;
size_t sizeInput= 0;
printf("Commands:\n");
/// put your other printfs here, then
ssize_t lengthInput = getline(&userInput, &sizeInput, stdin);
if (lengthInput < 0 || userInput==NULL)
{ perror("input error"); exit(EXIT_NULL); };
Now you have the entire typed line in userInput (including the terminating newline) and you know that its length is lengthInput. You can parse that line, perhaps using sscanf(3) (hint: use its return count, and consider using %n) or just using other techniques (some strcmp, or strtok(3)...). When done, you should free(userInput).
Notice that scanf (or sscanf) do not allocate any memory for parsed data, unless you use %ms (which is probably POSIX specific). With %s it always expecting some fixed length buffer, and for a array buffer declared char buf[64]; you'll better give the size with %63s; BTW, you should always test the result count of scanf. So you might code (after the above)
char nambuf[64];
if (sscanf(userInput, "a %63s", nambuf)==1) {
// use nambuf to add it
}
else if (sscanf(userInput, "r %63s", nambuf)==1) {
// use nambuf to remove it
}
(but the above is a bit silly, we read an arbitrary sized line but process nambuf of at most 63 bytes). You could just use scanf like if (scanf("a %63s", nambuf)==1) without needing any userInput.
Alternatively, you could use the Linux specific %as or better the POSIX specific %ms like:
char* nameptr=NULL;
if (scanf("a %ms", &nameptr)==1) {
then that successful scanf would have malloc-ed and filled nameptr and you should later free(nameptr). If you want to accept only lowercase letters consider coding something like if (scanf("a %m[a-z]", &nameptr)==1) etc...
This statement will allocte 4 bytes of data as userinput is pointer.
userInput = (char*)malloc(sizeof(userInput));
as pointed by the above answer this will cause a buffer overflow when the string size is more than 3 bytes.
also i would suggest fgets() over scanf when reading a string
sample code -
#include <stdio.h>
#include <stdlib.h>
int main() {
// your code goes here
char *userinput = (char *)malloc(100);
fgets(userinput,100,stdin);
printf("%s",userinput);
return 0;
}

Why does gets() assuming extern returning int in this code in C?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
int length;
char **lines, buffer[80];
printf("How many lines do you want to enter?.\n");
scanf("%d", &length);
getchar();
lines = (char**)malloc(length * sizeof(char*));
for (i = 0; i < length; ++i) { //Scan user's lines
gets(buffer);
lines[i] = (char*)malloc(strlen(buffer) * sizeof(char) + 1);
if (!lines[i]) { //Check if allocation available
printf("Error! Out of memory!");
return endProgram;
}
strcpy(lines[i], buffer);
}
return 0;
}
I'd like to know why does the gets() function giving me an error about assuming extern returning int, I'm just trying to scan a string.
The most likely reason is that gets() function has been deprecated for some time. It looks like it has been removed from <stdio.h> on your system.
Fortunately, this situation is easy to fix: replace the call with fgets(), like this:
fgets(buffer, sizeof(buffer), stdin);
Note: fgets is not a drop-in replacement for gets, because it keeps '\n' character at the end of line inside the string that it returns. This Q&A discusses the issue, and provides a solution.
The gets() function has been removed from the C Standard. It was never a good function to use because there is no way to tell gets how large the argument buffer is, making it very easy to cause buffer overflow or even malicious attacks if the input file is from an untrusted source. The reason your compiler complains about assuming extern returning int is that the prototype for gets is no longer present in your <stdio.h> system header.
Modify your code this way:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
int length;
char **lines, buffer[81];
printf("How many lines do you want to enter?.\n");
if (scanf("%d", &length) != 1)
return 1;
getchar(); // consuming the line feed typed by the user.
lines = malloc(length * sizeof(char*));
if (lines == NULL) {
printf("Error! Out of memory!\n");
return 2;
}
for (i = 0; i < length; i++) { //Scan user's lines
if (!fgets(buffer, sizeof buffer, stdin)) {
printf("Error! Premature end of file!\n");
return 2;
}
buffer[strcspn(buffer, "\n")] = '\0'; // overwrite the final \n
lines[i] = strdup(buffer);
if (lines[i] == NULL) {
printf("Error! Out of memory!\n");
return 2;
}
}
// perform other work on the buffer.
return 0;
}
gets() was deprecated in C99 and dropped from standard C with C11.
OP received the warning "about assuming extern returning int" because it is not prototyped in the standard include files.
To replace gets() with something else can be done approximately with fgets() #dasblinkenlight
With new code, use fgets() and its quirks.
To roll your own my_gets(char *dest, size_t size), with a high degree of former gets() compatibility, code should:
Take a size parameter that matches the size of the destination array.
Upon reading too many characters for the destination array, my_gets() is free to perform any reasonable functionality as the former gets() would cause undefined behavior at this point. Recommend filling the array as best as possible, consuming characters until '\n' or EOF, and returning NULL to indicate error (possible setting errno).
A simplistic use of fgets() is problematic as the size passed to fgets() is the space for characters, the '\n' and '\0', whereas the size passed to my_gets() really should be the space needed for the characters and '\0'. The '\n' being consumed and not saved.
A candidate function that meets these goals, using VLA, is at https://stackoverflow.com/a/34031881/2410359.

Reading string from input with space character? [duplicate]

This question already has answers here:
How do you allow spaces to be entered using scanf?
(11 answers)
Closed 4 years ago.
I'm using Ubuntu and I'm also using Geany and CodeBlock as my IDE.
What I'm trying to do is reading a string (like "Barack Obama") and put it in a variable:
#include <stdio.h>
int main(void)
{
char name[100];
printf("Enter your name: ");
scanf("%s", name);
printf("Your Name is: %s", name);
return 0;
}
Output:
Enter your name: Barack Obama
Your Name is: Barack
How can I make the program read the whole name?
Use:
fgets (name, 100, stdin);
100 is the max length of the buffer. You should adjust it as per your need.
Use:
scanf ("%[^\n]%*c", name);
The [] is the scanset character. [^\n] tells that while the input is not a newline ('\n') take input. Then with the %*c it reads the newline character from the input buffer (which is not read), and the * indicates that this read in input is discarded (assignment suppression), as you do not need it, and this newline in the buffer does not create any problem for next inputs that you might take.
Read here about the scanset and the assignment suppression operators.
Note you can also use gets but ....
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.
Try this:
scanf("%[^\n]s",name);
\n just sets the delimiter for the scanned string.
Here is an example of how you can get input containing spaces by using the fgets function.
#include <stdio.h>
int main()
{
char name[100];
printf("Enter your name: ");
fgets(name, 100, stdin);
printf("Your Name is: %s", name);
return 0;
}
scanf(" %[^\t\n]s",&str);
str is the variable in which you are getting the string from.
The correct answer is this:
#include <stdio.h>
int main(void)
{
char name[100];
printf("Enter your name: ");
// pay attention to the space in front of the %
//that do all the trick
scanf(" %[^\n]s", name);
printf("Your Name is: %s", name);
return 0;
}
That space in front of % is very important, because if you have in your program another few scanf let's say you have 1 scanf of an integer value and another scanf with a double value... when you reach the scanf for your char (string name) that command will be skipped and you can't enter value for it... but if you put that space in front of % will be ok everything and not skip nothing.
NOTE: When using fgets(), the last character in the array will be '\n' at times when you use fgets() for small inputs in CLI (command line interpreter) , as you end the string with 'Enter'. So when you print the string the compiler will always go to the next line when printing the string. If you want the input string to have null terminated string like behavior, use this simple hack.
#include<stdio.h>
int main()
{
int i,size;
char a[100];
fgets(a,100,stdin);;
size = strlen(a);
a[size-1]='\0';
return 0;
}
Update: Updated with help from other users.
#include <stdio.h>
// read a line into str, return length
int read_line(char str[]) {
int c, i=0;
c = getchar();
while (c != '\n' && c != EOF) {
str[i] = c;
c = getchar();
i++;
}
str[i] = '\0';
return i;
}
Using this code you can take input till pressing enter of your keyboard.
char ch[100];
int i;
for (i = 0; ch[i] != '\n'; i++)
{
scanf("%c ", &ch[i]);
}
While the above mentioned methods do work, but each one has it's own kind of problems.
You can use getline() or getdelim(), if you are using posix supported platform.
If you are using windows and minigw as your compiler, then it should be available.
getline() is defined as :
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
In order to take input, first you need to create a pointer to char type.
#include <stdio.h>
#include<stdlib.h>
// s is a pointer to char type.
char *s;
// size is of size_t type, this number varies based on your guess of
// how long the input is, even if the number is small, it isn't going
// to be a problem
size_t size = 10;
int main(){
// allocate s with the necessary memory needed, +1 is added
// as its input also contains, /n character at the end.
s = (char *)malloc(size+1);
getline(&s,&size,stdin);
printf("%s",s);
return 0;
}
Sample Input:Hello world to the world!
Output:Hello world to the world!\n
One thing to notice here is, even though allocated memory for s is 11 bytes,
where as input size is 26 bytes, getline reallocates s using realloc().
So it doesn't matter how long your input is.
size is updated with no.of bytes read, as per above sample input size will be 27.
getline() also considers \n as input.So your 's' will hold '\n' at the end.
There is also more generic version of getline(), which is getdelim(), which takes one more extra argument, that is delimiter.
getdelim() is defined as:
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
Linux man page
If you need to read more than one line, need to clear buffer. Example:
int n;
scanf("%d", &n);
char str[1001];
char temp;
scanf("%c",&temp); // temp statement to clear buffer
scanf("%[^\n]",str);
"%s" will read the input until whitespace is reached.
gets might be a good place to start if you want to read a line (i.e. all characters including whitespace until a newline character is reached).
"Barack Obama" has a space between 'Barack' and 'Obama'. To accommodate that, use this code;
#include <stdio.h>
int main()
{
printf("Enter your name\n");
char a[80];
gets(a);
printf("Your name is %s\n", a);
return 0;
}
scanf("%s",name);
use & with scanf input

Resources