In my C code I am given the following string as input:
"c:\tc\bin\a c j k.jpg"
I tried to read the input with scanf but it failed (passing the input both with and without quotation marks) and I am looking for an other solution.
My code is as follows:
char keytext[16],zzz,source[100],dest[100];
short int a;
size_t readcount;
clrscr();
printf("input the key text(max 16 characters):");
scanf("%s",&keytext);
printf("input file name:");
scanf("%s",&source);
/*fgets(source,100,stdin);
namelen=strlen(source);
if(source[namelen-1]=='\n')
source[namelen-1]='\0';*/
printf("output file name:");
scanf("%s",&dest);
The format specifier %s will stop consuming input when the first whitespace character is encountered, so it will only read until the end of C:\tc\bin\a. To read up to the k.jpg you can use a scanset:
char input[128];
if (1 == scanf("%127[^\n]", input))
{
}
The format specifier "%127[^\n]" means read up to the next newline character but no more than 127 characters to prevent buffer overrun. You should check the return value of scanf() before using its output, it returns the number of assignments made.
scanf function with %s specificator expects pointer to char char *. But you pass the pointer to pointer to char char **.
In order to fix it use the following code instead:
scanf("%s", keytext);
scanf("%s", source);
scanf("%s", dest);
Note, it doesn't require & symbol.
If you want to read whole string with spaces, you can use fgets function.
fgets(keytext, sizeof(keytext), stdin);
fgets(source, sizeof(source), stdin);
fgets(dest, sizeof(dest), stdin);
Related
I have some issues whith inputs from keyboard in C.
My input shoud be:
string with spaces
string with spaces
int
float
This declaration of input worked, but if first I enter int and float and then strings:
char title[60], author[50];
int year;
float rate;
char temp;
scanf("%d", &year);
scanf("%f", &rate)
scanf("%c",&temp);
scanf ("%[^\n]", title);
scanf("%c",&temp);
scanf ("%[^\n]", author);
With another order input behaves unpredictably.
I need a fast and efficient way to read inputs in the exactly order I described above.
scanf leaves a newline character (\n) in the buffer, for chained scanfs, when reading characters or strings you'll need to get rid of those, a simple solution is to add a space before the specifier, wether it's %s, %c or %[ ].
For your code, mixing the scanfs around:
scanf(" %59[^\n]", title);
scanf("%f", &rate);
scanf(" %49[^\n]", author);
scanf("%d", &year);
This should parse all your inputs correctly. As would any other reordering, provided that you then input the values in the correct order.
Live demo
I added size limits to the strings in scanf, you should always do this to avoid buffer overflow.
Verifying the return values of scanf is also advised to make sure the inputs were read correctly, e.g.:
if(scanf(" %59[^\n]", title) == 1){
//Ok
}
else{
//Deal with bad input
}
Note that if you want a more robust way to parse inputs that allow you to perform complete input checks, you shoud use fgets generally and then strtol / strtof to parse the numerical inputs.
With another order input behaves unpredictably.
This is due to the left-over '\n' after reading a number.
Rather than patch broken scanf(), read a line of user input with fgets() and then parse.
Easy and simply to re-order parsing as needed.
char buffer[100] = { 0 };
char title[60] = { 0 };
char author[50] = { 0 };
int year;
float rate;
fgets(buffer, sizeof buffer, stdin);
year = atoi(buffer);
fgets(buffer, sizeof buffer, stdin);
rate = atof(buffer);
fgets(buffer, sizeof buffer, stdin);
sscanf(buffer, "%59[^\n]", title);
fgets(buffer, sizeof buffer, stdin);
sscanf(buffer, "%49[^\n]", author);
Robust code would employ checks of fgets(), sscanf(), long lines and use strtol() and strtof().
scanf ("%[^\n]%*c", title);
scanf ("%[^\n]%*c", author);
scanf("%d", &year);
scanf("%f", &rate);
with this %*c, it reads newline character and here used * indicates that this newline character is discarded.
it works fine.
I'm writing a program to find the location of a certain character in a string using strchr. When using fgets to input the string from the user, the program does not execute properly.
However when using gets everything works fine.
Code that works using gets():
#include <stdio.h>
#include <string.h>
int main() {
char let;
char input[50];
char *ptr;
printf("what is the string that you would like to check?\n");
gets(input);
printf("what is the character that you would like to find?\n");
let = getchar();
printf("in string \"%s\"...\n", input);
ptr = strchr(input, let);
while (ptr != NULL) {
printf("the letter %c was found at character %d\n", let, ptr - input + 1);
ptr = strchr(ptr + 1, let);
}
return 0;
}
Output:
what is the string that you would like to check?
what is the character that you would like to find?
in string "why is the world when wondering"...
the letter w was found at character 1
the letter w was found at character 12
the letter w was found at character 18
the letter w was found at character 23
Code that does not work usgin fgets():
#include <stdio.h>
#include <string.h>
int main() {
char let;
char input[50];
char *ptr;
printf("what is the string that you would like to check?\n");
fgets(input, 16, stdin);
printf("what is the character that you would like to find?\n");
let = getchar();
printf("in string \"%s\"...\n", input);
ptr = strchr(input, let);
while (ptr != NULL) {
printf("the character is found at %d \n", ptr - input + 1);
ptr = strchr(ptr + 1, let);
}
return 0;
}
Output:
what is the string that you would like to check?
what is the character that you would like to find?
in string "abcdefghijklmno"...
Change
fgets(input, 16, stdin)
to
fgets(input, sizeof(input), stdin)
When you pass an argument of 16 to fgets() you are instructing it to read no more than 15 characters. Why?
From the fgets() manpage:
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s.
If you provide more than size -1 characters, the remaining characters are left in the input buffer.
Then when the program subsequently calls
let = getchar();
let is assigned whatever the next character in the input buffer is - without even waiting for you to type anything else. It then searches for this character in the string you provided - but in the example you provided doesn't find it.
In the first code snippet the call
gets (input);
does not restrict the number of characters the user can input. Take into account that the function gets is not supported by the C Standard and is unsafe.
In the second code snippet you declared the variable input as
char input[50];
So it is more natural to call fgets the following way
fgets (input,sizeof( input ),stdin );
instead of
fgets (input,16,stdin);
The standard function getchar reads any character including white spaces.
So instead it it is much better to use
scanf( " %c", &let );
Otherwise getchar can read any character (including for example the new line character) leaved in the input buffer. While the call of scanf will skip any white space character.
I can't take inputs except string.
If I give inputs in code itself, program is working.
But when I try to take inputs, its not working.
How do I get it to accept given inputs?
For example, if s were "codebook", and from == 'o' and to == 'e', s would become "cedebeek".
#include<stdio.h>
#define MAX 50
void replace(char *s, char from, char to)
{
int i=0;
while(s[i]!='\0')
{
if(s[i]==from)
{
s[i]=to;
}
i++;
}
}
int main()
{
char str[MAX];
char from;
char to;
printf("Enter the string");
scanf("%[^\n]s",&str[0]);
printf("\nEnter the character to be replaced");
scanf("%c",&from);
printf("\nEnter the character to be replaced with");
scanf("%c",&to);
replace(str, from, to);
printf("\nThe modified string is %s",str);
return(0);
}
There are a couple of problems in the posted code. Since arrays decay to pointers to their first elements in most expressions, there is no need for the address operator & in the call to scanf(); also, the trailing s is not part of the scanset conversion specifier:
scanf("%[^\n]", str);
As pointed out by #M.M in the comments, it is not incorrect to use &str[0] here instead of str, but it is more idiomatic, and I personally find it more clear, to use the less cluttered str.
When scanf() returns, a newline character will be left in the input stream, so you should add a leading space in the next call to scanf() to skip over this \n character before reading the user input:
scanf(" %c",&from);
And this call to scanf() will also leave a \n character in the input stream, so again:
scanf(" %c",&to);
Note that you should really specify a maximum width to avoid buffer overflow when reading user input into a string; there is no easy way to do this with MAX, but you can do:
scanf("%49[^\n]", str);
You could further improve code and ensure that input is as expected by checking the values returned by the calls to scanf().
i am a learner of 'C' and written a code, but after i compile it, shows a Debug Error message, here is the code:
#include<stdio.h>
void main()
{
int n,i=1;
char c;
printf("Enter Charecter:\t");
scanf("%s",&c);
printf("Repeat Time\t");
scanf("%d",&n);
n=n;
while (i <= n)
{
printf("%c",c);
i++;
}
}
Pls tell me why this happens and how to solve it
The scanf("%s", &c) is writing to memory it should not as c is a single char but "%s" expects its argument to be an array. As scanf() appends a null character it will at the very least write two char to c (the char read from stdin plus the null terminator), which is one too many.
Use a char[] and restrict the number of char written by scanf():
char data[10];
scanf("%9s", data);
and use printf("%s", data); instead of %c or use "%c" as the format specifier in scanf().
Always check the return value of scanf(), which is the number of successful assignments, to ensure subsequent code is not processing stale or uninitialized variables:
if (1 == scanf("%d", &n))
{
/* 'n' assigned. 'n = n;' is unrequired. */
}
scanf("%s",&c); should be scanf("%c",&c);
The %s format specifier tells scanf you're passing a char array. You're passing a single char so need to use %c instead.
Your current code will behave unpredictably because scanf will try to write an arbitrarily long word followed by a nul terminator to the address you provided. This address has memory allocated (on the stack) for a single char so you end up over-writing memory that may be used by other parts of your program (say for other local variables).
I'm not sure you understood the answer to your other question: Odd loop does not work using %c
These format specifiers are each used for a specific job.
If you want to get a:
character from stdin use %c.
string (a bunch of characters) use %s.
integer use %d.
This code:
char c;
printf("Enter Character:\t");
scanf("%c",&c);
Will read 1 character from stdin and will leave a newline ('\n') character there. So let's say the user entered the letter A in the stdin buffer you have:
A\n
The scanf() will pull 'A' and store it in your char c and will leave the newline character. Next it will ask for your int and the user might input 5. stdin now has:
\n5
The scanf() will take 5 and place it in int n. If you want to consume that '\n' there are a number of options, one would be:
char c;
printf("Enter Character:\t");
scanf("%c",&c); // This gets the 'A' and stores it in c
getchar(); // This gets the \n and trashes it
Here is a working version of your code. Please see inline comments in code for fixes:
#include<stdio.h>
void main()
{
int n,i=1;
char c;
printf("Enter Character:\t");
scanf("%c",&c);//Use %c instead of %s
printf("Repeat Time\t");
scanf("%d",&n);
n=n;//SUGGESTION:This line is not necessary. When you do scanf on 'n' you store the value in 'n'
while (i <= n)//COMMENT:Appears you want to print the same character n times?
{
printf("%c",c);
i++;
}
return;//Just a good practice
}
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