I'm writing a basic program to learn how to use basic input/output in C, and it works just fine. The only problem I have is when it prints, there is a "%" at the end of the string on the terminal. Here's my code:
#include <stdio.h>
int main(int argc, char **argv) {
char name[32];
printf("Enter your name: ");
scanf("%s", name);
printf("Hello, %s", name);
return 0;
}
When I run the program, the output is Hello, Andrew%
Any help?
There's nothing in your code that should explain this behavior. However, it seems likely that if you are running this from a shell, that may be your shell prompt.
Add a newline to your output:
printf("Hello, %s\n", name);
This should cause the prompt to print on the next line as you probably expected.
The stdout stream is line buffered. What this means is the output does not appear on the console until a newline is output or the buffer is full. This may be a cause why you are seeing a % on the screen. '\n' causes printf to print the output immediately on the screen.
Note that if the input string is larger than 31 characters, then scanf will overrun the buffer name invoking undefined behaviour. This may crash the program due to segfault. You should safeguard against it by providing the maximum field width which should be 1 less than the array length to accommodate for the terminating null byte added by scanf.
#include <stdio.h>
// if your not using command line argument, use the below
// signature of main
int main(void) {
char name[32];
printf("Enter your name: \n"); // add a newline to output
scanf("%31s", name); // -1 for the terminating null byte
printf("Hello, %s\n", name); // add a newline to output
return 0;
}
As you have not output a new line - that is your shell prompt character being shown after the specified output. Try printf("Hello, %s\n", name);
Run this command line PROMPT_EOL_MARK='' into your zsh shell, that should be enough to fix it.
Related
I wanna reproduce the terminal behavior when the input is just a new line (keeps printing the same string), but don't know how to do it.
Example: When the user just inputs a new line, the terminal keeps printing the directory, until a real command is inserted
int main()
{
char userInput[1024];
while (1)
{
printf("directory »» ");
scanf("%[^\n]" , userInput); // This scanf doesn't work
while (userInput[0] == '\n') // If the input is only a new line char, keep asking for more inputs and printing the directory
{
printf("directory »» ");
scanf(" %[^\n ]" , userInput); // This scanf doesn't work
}
//Input isn't a NewLine, process the input
process_Input_Function(userInput); //Isn't empty, search for my created commands
}
}
At the first enter press, it enters the loop, reproduce 1 time, and then the scanf doesn't detect new lines anymore, it just skips and waits to a real string.
What can i type inside of the scanfto detect a new line input and keep printing that string till a real command is inserted?
I tried with scanf("%c"...) but the problem with a char, is that i can't process the whole string command, if isn't empty
First of all, your two scanf calls are different. The first one is
scanf("%[^\n]", userInput);
which looks for anything that's not a newline, as you wish to do.
But the second one is
scanf(" %[^\n ]", userInput);
which is also looking for a space before the input, followed by any character that is also not a newline or a space. Thus, scanf is waiting for the space.
IMHO, the best way to recreate this behavior is going to be in the parsing step, after you have gotten the command from the command line. Essentially, your command input loop would look like this:
char *userInput = NULL;
size_t n = 0;
while (true) {
// print the prompt
printf(">");
// get the line
ssize_t userInputLength = getline(&userInput, &n, &stdin);
// parse the input, using a function you wrote elsewhere
parse(userInputLength, userInput);
}
(Note the use of POSIX getline() instead of scanf. This is a more recent standard library function that does exactly the task of getting a line of user input, and also allocates the buffer using malloc and realloc so that you don't have to care about buffer overflows or even sizing the buffer at all.)
The user input function wouldn't care that the userInput portion was blank. The function that would care is the parse function, which will simply interpret a blank userInput string as "do nothing" and continue on its merry way.
Hmm, the code I gave pretty much does that with one exception, it doesn't display a prompt each time...
Is this what you mean:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // For the memset()
int main() {
char userInput[1024];
while (1) {
printf("»»» ");
fgets(userInput, 1024, stdin);
while (userInput[0] == '\n')
{
printf(">>> ");
memset(userInput, '\0', 1024);
fgets(userInput, 1024, stdin);
}
// Your command can be accessed from here //
printf("Command entered: %s\n", userInput);
printf("Input isn't a NewLine\n");
}
}
I changed the scanf() to fgets() to read from stdin so that we don't overwrite the buffer.
So that's my code, but every time I run it the command window crashes right after I input a name. I'm using Visual Basic, so it gives me a warning when I try to use:
scanf()
so instead i decided to use:
scanf_s
I also tried to change the %s in scanf_s("%s\n", name) to %c. It stopped crashing and executed the program but when it prints the name, it would just be a bunch of broken text.
#include <stdio.h>
int main(void) {
char name[30];
printf("Enter your name:\n");
scanf_s("%s\n", &name);
printf("%s\n", name);
}
Change the scanf line to
scanf("%29s", name);
Since your array has 30 positions, it shouldn't read more than 29. The last one is for the null terminating char
so I was messing with the read functions fgets and scanf and with the printing functions write and printf with the following code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
printf("Enter an integer: ");
int n = 0; scanf("%d",&n);
printf("The input number is: %d\n", n);
printf("Please enter a string now: ");
char buffer[200];
read(0,buffer,200);
printf("The input string is: %s", buffer);
printf("which is: %s\n", buffer);
printf("Now please enter another message: ");
fgets(buffer,200,stdin);
write(1,buffer,200);
return 0;
}
I would get these errors:
1-After the first scanf, it won't just show me the message to input the string.
2-What I write now it's what it's going to be saved in the string.
3-It will skip the last fgets...
An example of output:
Which doesn't make any sense at all; I would like to get an output like this:
Enter an integer: 15
The input number is: 15
Please enter a string now: This is the message1
The input string is: This is the message1 which is: This is the message1
Now please enter another message: This is the message2
This is the message2
Thanks for your help!
Interesting question. Mixing standard I/O (scanf(), fgets()) and file descriptor I/O (read()) on the same underlying file descriptor (0 aka standard input; stdin as a file stream) is at best problematic. You will get odd-ball effects.
At the file stream level, there is some synchronization between stdin and stdout when the input comes from a terminal; pending output on stdout is often flushed by the library. When you use read(), there is no such synchronization. That's why the prompt doesn't appear until after you hit return.
When you type 1 for the number, you also supply a newline. Standard I/O buffers the newline; it is kept so that the next file stream operation can read it. Then you read a line with read(). This does not know about the standard I/O buffer, so it waits for a new line of input from the terminal. You need to capture how much data was read because the input was not null terminated; that's a service provided by the standard I/O library, not the low-level read() function.
When you then call fgets(), it reads the newline that was buffered (not processed by scanf() when reading the integer) and returns with the empty line.
Note that if you had any buffered output waiting on standard output (e.g. you had used printf("Beginning of line: "); with no newline), then the output from write() would appear before the information buffered on stdout.
Using fread() and fwrite() would give you direct binary I/O (no null termination, for example), but would use the same I/O buffers as functions such as printf() and fgets(). You get hybrid behaviour when using these — it is normally best to use either fread()/fwrite() or the text I/O functions on a single file stream, and not both, but mixing them is permissible, relatively simple to understand, and occasionally useful.
So, what you see is all explainable, but it is hard work doing the explaining. It is also a clear indication of why you should not, in general, mix file stream and file descriptor I/O on the same underlying file descriptor — especially not standard input.
Why not use scanf with some better formatting:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
int n, i;
char buffer[200], ch;
printf("Enter an integer: ");
scanf("%d",&n);
printf("The input number is: %d\n", n);
printf("Please enter a string now: ");
scanf(" %[^\t\n]s",buffer);
printf("The input string is: %s", buffer);
printf("which is: %s\n", buffer);
printf("Now please enter another message: ");
scanf(" %[^\t\n]s",buffer);
printf("%s", buffer);
return 0;
}
read(0,buffer,200);
reads up to 200 characters but it won't add a terminating null character to buffer. Hence the following call to printf results in undefined behavior.
You need to add code to capture the return value of the function and make sure to null terminate the string.
int n = read(0, buffer, 199); // Leave one for the terminating null character
if ( n == -1 )
{
// Deal with the error.
}
else
{
// null terminate the string.
buffer[n] = '\0';
}
I am creating a c shell and having an issue where I am stuck in an infinite loop. Example input/ouput: I type "ls -a" and the results of the command continually print over and over to console. If I remove the label (I called start:) and the goto statement then my shell will just execute the command and then exit the shell program entirely. I have also tried using while(1) and for(;;) loops but these resulted in the same output I am currently getting. How can I accomplish my goal here? all help is appreciated. see code below.
int main( int argc, const char* argv[]){
char whole[1024];
int cmdCount = 1;
start:
scanf("%1023[^\t\n]", whole);
//....
goto start;
return 0;
}
Your scanf will read everything except newline or tab. You never check if it reads anything. So the first time it succeeds, the next time there's a newline so it can't read anything. You don't check this and just use the buffer which contains the previously read line. This will cause the same command to be run over and over again.
Rather read lines from stdin and parse them, don't read with scanf.
The problem is you didn't check return of value of your scanf function. First it scans everything up to \n character and executes your code. But the \n character is still left in buffer; So next scanf will do nothing, leaving old whole value intact. That's why it's executing the same command over and over again. Check the following code:
#include <stdio.h>
#include <string.h>
int main(void) {
char whole[1024];
strcpy(whole, "override whole string");
scanf("%1023[^\t\n]", whole);
printf("%s\n", whole);
strcpy(whole, "override whole string");
scanf("%1023[^\t\n]", whole);
printf("%s\n", whole);
return 0;
}
It won't allow you to enter two lines. Second scanf will just fail, leaving old "overridden" value.
Use fgets function to get whole lines of input.
I'm trying to ask the user to type in a string so I will print the length of the string. My code is built succeeded. However, when I entered a word and pressed 'enter', the program keeps running. I had to enter a second word, then the length of the first string displays. I'm confused at argv[1]. Can someone give me some tips and hint on how to fix this? Thanks in advance for your time.
Please note that I'm not allowed to use any string function.
int main(int argc, char* argv[]){
char* s=argv[1];
char input[256];
s = input;
printf("Please enter a string: ");
scanf("%s\n", s);
int str_length = 0;
while (s[str_length] != '\0')
{
str_length++;
if (s[str_length] == '\0') break;
}
printf("%d\n", str_length);
return 0;
}
argv[] is the array that holds your command line parameters, argv[1] is the first one (other than the command representation itself in argv[0], of course). You assign it to s then immediately overwrite s, so it's not really needed here.
The reason you're having to enter two lines is the \n at the end of your input format. It requires whatever can match the format string followed by a newline, hence the %s\n is eating your first newline so that scanf has to go back for another one.
%s on it's own will fix that problem but introduce another one if what you're after is a full line of input - it will only read up to the first whitespace. For a proper line input function, see here.
It does full line input with protection against buffer overflows and detection/cleanup of lines that were too long, something sorely missing in the scanf("%s") input method.
In addition, the if statement within the while is superfluous here since the while itself will catch the end of the string, and it makes little sense to have both input and s refer to the same array (it would make sense if you changed s at some point, but that's not happening here).
So, a variant without the advanced line iput function could be as simple as:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char* argv[]) {
char input[256];
int str_length = 0;
printf ("Please enter a string: ");
scanf ("%s", input);
while (input[str_length] != '\0') /* Or consider using strlen() */
str_length++;
printf ("%d\n", str_length);
return 0;
}
If you enter Hello, you'll see that it prints out 5 immediately. You'll also see 5 if you enter Hello Pax, which is one reason to choose the advanced input function (the other, very important, reason is to avoid introducing a buffer overflow vulnerability into your program).
argv is used to pass process arguments. this means you can run your program like
a.out 123 abcd
argv[1] will already be assigned to a value of 123. you do not have to read it as you are doing now. in your current code , you are overwriting the reference of s to a new string after assigning it with argv[1].
This is what you want
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX 100
int main(int argc, char* argv[]){
char tmp[MAX];
printf("Plese enter a string:\n");
scanf("%s", tmp);
printf("the length is %d\n", strlen(tmp));
return 0;
}
The argv and argc is another thing like this:
argv[0] = a.exe
argv[1] = 12345
int main(int argc, char* argv[]){
printf("the length is %d\n", strlen(argv[1]));
return 0;
}
/*-------------------- Output --------------------
> a.out 12345
the length is 5
------------------------------------------------*/
Just change the scanf line:
scanf("%s", s);
As you have it (scanf("%s\n", s);), it requires a sequnce of characters ending in \n, then another \n to indicate when the input is finished.