I'm attempting to learn C and decided to use Visual Studio as a base for where I can practice my code. I have everything set up already and have started writing up code as well but I seem to be running into a problem where I cannot see the user input.
Here is my program:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char string[] = "";
char reversed[] = "Placeholder";
printf("Please enter an input string.\n");
scanf("%s", &string);
printf("Your original string is %s\n", string);
printf("The string reversed is %s", reversed);
return 0;
}
When I run this program, the first printf statement is never printed nor is the user input ever shown
anywhere (not in the terminal either). All it says is that the program is running. When I force stop it,
it will say 'Done!' and that's all that ever happens (I have to force stop because I never see the place to input the string therefore the program just keeps running waiting for an input). I just set up Visual Studio so it is possible I missed something and this is an easy fix but not quite sure what it is.
The string you're inputting is empty. First avoid naming variables "string" as in standard libraries there might already be defined one. And try to allocate more space for your string to be able to input data.
`
char str[128];
char reversed[] = "Placeholder";
printf("Please enter an input string.\n");
scanf("%s", &str);
printf("Your original string is %s\n", str);
printf("The string reversed is %s", reversed);
return 0;
`
Also, be sure to read more about arrays, strings and functions in c. The code you've written is probably not gonna work as you've intended.
There are a couple of problems.
You're not allocating any memory for string, so when the user inputs something, its written into memory it doesn't own, resulting in undefined behavior.
Your scanf is wrong,, kind of. You must provide it a pointer to the memory where the input should go, you're providing the address of the pointer. In this case, they're one in the same, but if that was a pointer to heap memory, for instance, &string would not point to the memory you've reserved.
Instead, try something like this:
int main()
{
char string[64] = ""; // string can now hold 63 user-input characters plus
// one for the NUL terminator, which scanf will add
// automatically.
char reversed[] = "Placeholder"; // This reserves at least 12 bytes, 11 for the text plus the NUL terminator.
printf("Please enter an input string.\n");
scanf("%s", string); // string decays to a pointer to where its memory is allocated.
printf("Your original string is %s\n", string);
return 0;
}
Note, you can still overflow your string buffer if you enter (in this case) more >= 64 characters, and you'll be back where you started. I believe there is a way for scanf to limit the amount of input accepted, but will need to look up how. Another option is to use fgets to accept limited input.
Related
I'm trying to make a loop that does not stop until the user inputs a string. For ex. if the user inputs a number or a letter it will say Invalid input until the user enters a string.
But for some strange reason, when I run my code and I input a string, the program continues to loop the block of code. Here's the output
#include <stdio.h>
int main() {
char name[100];
char letter[100];
lt:
printf("\033[0;33m");
printf("\nEnter your Name:\ni.e. Miguel\n");
printf("\033[0m");
scanf("%s", name);
if (name != letter) {
printf("\033[0;31m");
printf("Invalid input");
printf("\033[0m");
goto lt;
}
return0;
}
I've tried the goto function to loop the code but seems like that isn't working.
Uninitialized variables:
char letter[100];
letter is used uninitialized in your code. It's contents are indeterminate. Variables declared with automatic storage aren't implicitly initialised to 0.
Comparing strings:
if (name != letter)
This only compares the pointer addresses (and I believe it invokes undefined behavior), not the contents of the what those pointers point to.
The C standard library provides a function strcmp that compares two strings.
Note: It's declared in string.h.
Buffer overflow vulnerability:
scanf("%s", name);
is similar to using gets (in terms of limiting input). scanf will happily continue to read from stdin until it sees a whitespace, ignore everything to the right hand side of the whitespace, (which leads to more problems down the road) and potentially overflow the buffer.
You could use a field width to limit input:
scanf("%99s", name);
Or even better, use fgets.
fgets(name, sizeof(name), stdin);
It will read at most n - 1 characters and null-terminate the string.
Side-note: fgets will store the \n character in the buffer, which might not be what you want. Here's one way to remove it¹:
name[strcspn(name, "\n\r")] = '\0';
scanf returns the number of successful conversions:
Ignoring the return value of scanf gainsays the 6th commandment of Henry Spencer's "The Ten Commandments for C Programmers":
If a function be advertised to return an error code in the event of
difficulties, thou shalt check for that code, yea, even though the
checks triple the size of thy code and produce aches in thy typing
fingers, for if thou thinkest ``it cannot happen to me'', the gods
shall surely punish thee for thy arrogance.
if (scanf("%99s", name) != 1) {
handle the error here..
}
Using goto:
While that is a legal use, it's discouraged. goto should not be used for such purposes.
Instead, as #SimonGoater suggested, use a while loop.
if the user inputs a number or a letter it will say Invalid input
until the user enters a string.
So the requirements are:
Names should be greater than 1 character.
Names shouldn't have any numbers in them. (But my friends have names with numbers, and even special characters. :-( )
Note:
You can't have a string with one char, unless that char is a null-byte.
Possible Solutions:
As strlen doesn't include the null-terminator, we can use it to calculate the length of the string, and if it equals 1, handle the error accordingly.
Iterate through the buffer character by character, and if you find a number or a special character, handle the error accordingly.
[1] You might want to give this a read for more:
https://codereview.stackexchange.com/q/67608
#include <stdio.h>
#include<conio.h>
#include<string.h>
int main(){
char name[100];
char letter[100]="amir";
lt:
printf("\033[0;33m");
printf("\nEnter your Name:\ni.e. Miguel\n");
printf("\033[0m \n");
scanf("%s",name);
if(strcmp(name, letter) != 0){
printf("\033[0;31m");
printf("Invalid input");
printf("\033[0m");
goto lt;
}
return 0;
}
What is going on here?
The code goes like:
#include<stdio.h>
#include<string.h>
int main()
{
char name[15];
char name_[15];
char answ[1];
printf("What's your name?\n");
scanf("%s", name);
strcpy(name_, name);
printf("Yes / No: ");
scanf("%s", answ);
printf("Hello! %s\n", name_);
printf("You said: %s\n", answ);
return 0;
}
With input "name" and "yes" the expected output is that it says:
Hello! name
You said: yes
Instead I get:
Hello! es
You said: yes
I also tried adding spaces before %s with no results.
So what exactly am I missing here?
answ can contain only 1 character. So currently, the extra character "es" + '\0' gets written into the memory assigned to name_.
So, "es" gets printed.
You've only allocated space for a one-character yes/no answer, but are writing more characters into it.
This results in undefined behaviour.
You need to allocate more space for answ, not forgetting about the NUL terminator.
You have created a classic exploitable buffer overrun but in your code. This is why most modern compilers would advise you to swap sscanf to sscanf_s or similar. As other people have pointed out, you overwrite the next variable on the stack.
I wanted to provide this answer to basically say: never ever use sscanf or any of the obsolete, insecure C functions. Even if this is probably just a toy example, get the practice in to write modern C code. You’ll benefit from this in the long run.
My goal with this program is to incorporate the users inputs into a sort of interactive/randomized story but I'm not sure how I'm supposed to get the inputs from the users to fit between *ptrDescription, *ptrBeginning, *ptrMiddle, and *ptrEnd. Any help would be much, much appreciated!
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include <string.h>
#include <ctype.h>
int main(void){
int i;
char name[20];
char color[20];
int age;
char sentence[1];
//array of pointers to char arrays
char *ptrDescription[]={"the painfully handsome","the one and only","who seemed much older than"};
char *ptrBeginning[]={"was blissfully ignoring","could clearly see","had no idea"};
char *ptrMiddle[]={"the huge truck","the falling meteor","the bucket of milk","the mailman","the most powerful wizard"};
char *ptrEnd[]={"that was barreling toward them.","on the horizon."};
srand(time(NULL));
printf("Enter your first name: ");
scanf("%s", &name);
printf("\nEnter your age: ");
scanf("%d", &age);
printf("\nEnter your favorite color: ");
scanf("%s", &color);
for (i = 0; i < 1; i++)
{
//strcpy(sentence,ptrDescription[rand()%3]);
//strcat(sentence," ");
//strcat(sentence,ptrBeginning[rand()%3]);
//strcat(sentence," ");
//strcat(sentence,ptrMiddle[rand()%5]);
//strcat(sentence," ");
//strcat(sentence,ptrEnd[rand()%2]);
//strcat(sentence,".");
//sentence[0]=toupper(sentence[0]);
puts(sentence);
}
getch();
return 0;
}
EDIT:
I've edited a section of my code so that directly following for (i = 0; i < 1; i++) it now looks like this:
snprintf(sentence, sizeof sentence,"%s, %s %d year old, %s %s %s %s", name, ptrDescription[rand()%3], age,ptrBeginning[rand()%3], ptrMiddle[rand()%5], ptrEnd[rand()%2]);
There are tons of strange characters after the sentence in the output, like Japanese characters and stuff. I'm not sure why they're there, though. This is what it looks like exactly:
"Enter your first name: Justin
Enter your age: 20
Justin, the arrogant 20 year old, was purposefully ignoring the most powerful wizard that was barreling toward them. 汽$0HβHζ(テフフフフフフフフフフフフフH・(DキHH広$0陏&・汽$0タHζ(テフフフフフフフフフフフフフフフH WH・ H櫛H・t9HνHテ<"
Anyone know how I can get rid of them?
If you already have a name and an age, it's just a matter of inserting them into the correct place in sentence, right? So strcat(sentence, name) would work for name. age is a little trickier since you have to format the number first, and strcat won't do it for you. One solution would be to use sprintf(buf, "%d", age), and then concatenate buf (which is a scratch char array you would have to declare).
Any time you work with strings in C, you have to be concerned about having enough space in the target buffer. Your program can run out of space during both input and output. For the output, I would get rid of sentence altogether; since you just end up writing to stdout I would printf("%s", [part]) each part as you go along. For reading, scanf supports adding a length argument to the format string.
If you use one of the *printf functions, there are 2 things you must be careful about:
The arguments you pass are correct for the format string you use
Your buffer ends up null-terminated
Your current problem is with #1 - your format string promises 7 arguments to follow, but you only supply 6. snprintf grabs a "random" 7th value from the stack, interprets it as a char pointer, and copies whatever it finds there to sentence. You could see similar problems if your format string promised a char pointer but you placed an int in a given position. In this case the format string is a constant, so a smart compiler can validate that your format string matches the subsequent parameters. You'll want to get into the habit of taking compiler warnings seriously and not ignoring them.
The second point could be an issue if your sentence ended up bigger than your sentence buffer. If there is no room for a null-terminator, one won't be applied. You can check the return value of snprintf, or you can defensively always write a 0 to the last array position.
Here you can see my source code:
#include <stdio.h>
int main()
{
char yourname;
char yoursex;
int yourage = 0;
printf("Hey, what's your name?\n");
printf("My name is: ");
scanf("%s", &yourname);
printf("Oh, hello %s! \n\n", &yourname);
printf("Are you a boy or a girl?: ");
scanf("%s", &yoursex);
printf("Nice to know you are a %s! \n\n", &yoursex);
printf("How old are you %s? I am ", &yourname);
scanf("%d", &yourage);
printf("I see you are %d, you have many years then!", &yourage);
return 0;
}
I was trying things that I didn't knew, and strangely it is not working for me. What's the problem? Also, why it needs to be %s and not %c? If I use %c instead it does not work!
Where it says:
How old are you %s? instead of putting my name, it says ''oy''
and instead of showing my age in the last line, it shows a big number.
These are the very basics of C Programming, and I strongly advise you to get a decent book - The C Programming Language by Dennis Ritchie would be a good start.
There are numerous errors in your code.
A char can contain only one character, like 'A', or 'a' or something like that. When you're scanning a name, it is going to be a group of characters, like 'E', 'd', 'd', 'y'. To store multiple characters, you need to use a character array. Also, the format specifier used to scan/print characters is %c, %s is for when you need to scan a group of characters, also called a string into an array.
When you use printf, you do not supply a pointer to the variable you are trying to print (&x is a pointer to variable x). The pointer is a 32/64-bit integer, which is likely why you see a random integer when trying to print. printf("%c\n", charVar) is sufficient.
scanf does not need an & while using %s as the format specifier, assuming you have passed a character array as the argument. The reason is, scanf needs to know where to store the data you are reading from the input - and that is given by a pointer to the memory location. When you need to scan an integer, you need to pass an &x - which means, pointer to memory location of x. But when you pass a character array, it is already in the form of a memory address, and doesn't need to be preceded by an ampersand.
I once again recommend you look up some decent tutorials online, or get a book (the one I mentioned above is a classic). Type the examples as given in the material. Experiment. Have fun. :)
%s is for reading a string -- multiple characters delimited by whitespace. %c is for reading a single char.
You declare your yourname and yoursex vars as characters, and then try to read strings into them. The string read will overwrite random other things in the stack frame and misbehave or crash.
You want to declare yourname and yoursex as character arrays, so they can hold strings:
char yourname[32];
char yoursex[32];
then, when reading into them, you want to include a length limit so they don't overflow:
scanf("%31s", yourname);
This is a single character:
char yourname;
But %s indicates that the variable is a string (i.e., an array of characters terminated by a NUL). That's why you need %c. If you really did mean to use a string, then define the variable like
char yourname[32]; /* just pick a big enough size */
Also, you are correct to use the address of the variable with scanf(), but printf() needs the value. So instead of
printf("I see you are %d, you have many years then!", &yourage);
use
printf("I see you are %d, you have many years then!", yourage);
The "big number" is the memory address.
Make sure you read the comments in code!
#include <stdio.h>
int main()
{
char yourname[10];
char yoursex[5]; // boy or girl + null terminator
int yourage = 0;
printf("Hey, what's your name?\n");
printf("My name is: ");
scanf("%s", &(*yourname)); // & and * cancel each other out,
// thus take a look at the next scanf()
printf("Oh, hello %s! \n\n", yourname); // yourname is now an array
printf("Are you a boy or a girl?: ");
scanf("%s", yoursex);
printf("Nice to know you are a %s! \n\n", yoursex);
printf("How old are you %s? I am ", yourname);
scanf("%d", &yourage); // ok
printf("I see you are %d, you have many years then!", yourage); // here you don't
// need the address of the variable!
return 0;
}
The expression char yourname; only holds space for a single character, so quite likely you end up corrupting the memory space when scanning for yourname. You should allocate a bigger buffer and make sure that you don't overrun its length by setting a maximum number of characters to be read with the scanf function; as described in some of the other answers.
The fact that the following printf print correctly the name doesn't mean that the memory doesn't get corrupted; as C/C++ don't really check the boundary of any strings or arrays used at runtime.
As suggested by others, starting by reading a good book about C and/or C++ wouldn't a bad idea.
int main()
{
//Define Variables
char studentName;
//Print instructions to fill the data in the screen
printf("Please type in the Students name:\n");
scanf("%s", &studentName);
printf("\n\n%s", &studentName);
return 0;
}
Seeing the above code, I am only printing to screen out the first word when I type in a sentence.
I know it is a basic thing, but I am just starting with plain C.
Read scanf(3) documentation. For %s is says
s Matches a sequence of non-white-space characters; the next
pointer must be a pointer to character array that is long
enough to hold the input sequence and the terminating null
byte ('\0'), which is added automatically. The input string
stops at white space or at the maximum field width, whichever
occurs first.
So your code is wrong, because it should have an array for studentName i.e.
char studentName[32];
scanf("%s", studentName);
which is still dangerous because of possible buffer overflow (e.g. if you type a name of 32 or more letters). Using %32s instead of %s might be safer.
Take also the habit of compiling with all warnings enabled and with debugging information (i.e. if using GCC with gcc -Wall -g). Some compilers might have warned you. Learn to use your debugger (such as gdb).
Also, take the habit of ending -not starting- your printf format string with \n (or else call fflush, see fflush(3)).
Learn about undefined behavior. Your program had some! And it misses a #include <stdio.h> directive (as the first non-comment significant line).
BTW, reading existing free software code in C will also teach you many things.
There are three problems with your code:
You are writing a string into a block of memory allocated for a single character; this is undefined behavior
You are printing a string from a block of memory allocated for a single character - also an undefined behavior
You are using scanf to read a string with spaces; %s stops at the first space or end-of-line character.
One way to fix this would be using fgets, like this:
char studentName[100];
//Print instructions to fill the data in the screen
printf("Please type in the Students name:\n");
fgets(studentName, 100, stdin);
printf("\n\n%s", &studentName);
return 0;
Try scanf("%[^\n]", &studentName); instead of scanf("%s", &studentName);
This is happening because %s stops reading the input as soon as a white space is encountered.
To avoid this what you can do is declare an array of the length required for your string.
Then use this command to input the string:-
scanf("%[^\n]s",arr);
This way scanf will continue to read characters unless a '\n' is encountered, in other words you press the enter key on your keyboard. This gives a new line signal and the input stops.
int main()
{
//Define Variables
char studentName[50];
//Print instructions to fill the data in the screen
printf("Please type in the Students name:\n");
scanf("%[^\n]s", &studentName);
printf("\n\n%s", &studentName);
return 0;
}
Alternatively you can also use the gets() and puts() method. This will really ease your work if you are writing a code for a very basic problem.
[EDIT] : As dasblinkenlight has pointed out...I will also not recommend you to use the gets function since it has been deprecated.
int main()
{
//Define Variables
char studentName[50];
//Print instructions to fill the data in the screen
printf("Please type in the Students name:\n");
gets(studentName); printf("\n\n");
puts(studentName);
return 0;
}
make the changes below and try it. I added [80] after the studentName definition, to tell the compiler that studentName is an array of 80 characters (otherwise the compiler would treat it as only one char). Also, the & symbol before studentName is not necessary, because the name of the array implicitly implies a pointer.
int main()
{
//Define Variables
char studentName[80];
//Print instructions to fill the data in the screen
printf("Please type in the Students name:\n");
scanf("%s", studentName);
printf("\n\n%s", studentName);
return 0;
}
Your problem is here
char studentName;
It is a char, not a string.
Try:
Define it as an array of chars like char studenName[SIZE];.
allocating memory dynamically using malloc:
.
char buffer[MAX_SIZE];
scanf("%s", &buffer);
char * studentName = malloc (sizeof(buffer) + 1);
strcpy (studentName , buffer);