Varying number of elements in scanf() - c

How do I tell my program how to vary how many elements are to be read by scanf? I want it to read each character in a string, and the length of the string may vary from one character to a hundred characters. I know I can do scanf("%c%c%c%c...") a hundred times but is there an easier way to do this?

Sure, use fgets() with an appropriately sized buffer:
char buf[LINE_MAX];
if (fgets(buf, sizeof buf, stdin) != NULL) {
// input is now in `buf'
}
If you really can't use arrays, then call getchar() until it finds a newline:
int sum = 0;
int ch;
while ((ch = getchar()) != EOF && ch != '\n') {
sum += ch;
}
(this already does what you want, i. e. it sums the character codes of the string the user enters.)

You can do this way
char A[105];
scanf("%s", A);
printf("%s\n", A);
By this, you can input string with various length. If you input "abc" then the result is "abc"

Related

Reading arbitrary length strings in C

I've attempted to write a C program to read a string and display it back to the user. I've tested it with a lot of input and it seems to work properly. The thing is that I'm not sure whether or not the c != EOF condition is necessary inside the while expression, and since by definition, the size of a char is 1 byte, maybe I can remove the sizeof(char) expressions inside the malloc and realloc statements, but I'm not sure about this.
Here's the program, also, I manually added a null terminating character to the string:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *str = malloc(sizeof(char));
if (!str)
return 1;
char c;
char *reallocStr;
size_t len = 0;
size_t buf = 1;
printf("Enter some text: ");
while ((c = getchar()) != '\n' && c != EOF) {
if (len == buf) {
buf *= 2;
reallocStr = realloc(str, buf * sizeof(char));
if (!reallocStr)
return 1;
str = reallocStr;
}
str[len++] = c;
}
str[len] = '\0';
printf("You entered: %s\n", str);
free(str);
return 0;
}
As mentioned in the comments, you have a buffer overflow in your code, so you would need to fix that at the very least. To answer your specific questions, sizeof(char) is guaranteed to be 1 (dictated by the c99 spec), so you don't need to multiply by sizeof(char). It's good practice to check for EOF as if your input is coming from an alternate source that has no newline, you don't die (so if someone for example did printf %s hello | yourprogram from a bash prompt, you wouldn't die).
Problems include
Buffer overflow
#HardcoreHenry
Incorrect type
getchar() reruns an int with the values [0..UCHAR_MAX] and the negative: EOF. These 257 different values lose distinctiveness when saved as a char. Possible outcomes: infinite loop or premature loop end. Instead:
// char c;
int c;
Advanced: Arbitrary length
For very long lines buf *= 2; overflows when buf is SIZE_MAX/2 + 1. An alterative to growing in steps of 1, 2, 4, 8, 16,..., consider 1, 3, 7, 15, .... That way code can handle strings up to SIZE_MAX.
Advanced: Reading '\0'
Although uncommon, possible to read in a null character. Then printf("You entered: %s\n", str); will only print to that null character and not to the end of input.
To print all, take advantage that code knows the length.
printf("You entered: ");
fwrite(str, len, 1, stdout);
printf("\n");
To be clear, text input here is not reading of strings, but of reading of lines. That input is saved and converted to a string by appending a null character. Reading a '\0' complicates things, but something robust code handles.

C: how to read many strings from stdin

I need to read many strings with a variable length from stdin up to EOF.
The strings are made of consecutive chars, not separated by blanks and there is not a maximum length for the strings.
Using:
char st[101];
while(scanf("%100s",st) != EOF){ //divide the input into parts of 100 chars
int i;
for(i=0; i<strlen(st);i++){
printf("%c",st[i]);
}
}
I can not tell if the current string is part of a previous one or a new one because it is printed all in a single line (and I've no idea where to print "\n").
Sample input:
aaaaaaaaa[...]aaaaa
bbbbbbbbb[...]bbbbb
output:
aaaa[...]aabbbbbb[...]bbbb
Any solution?
P.S. Using getchar() I'm not able to handle the EOF.
Here's how you handle EOF with getchar:
int c;
while ((c = getchar()) != EOF) {
putchar(c);
}
This code will replicate its input on stdout.
If you want to deal with whole lines at a time, the easiest way is to use getline if you have it (it's POSIX, not standard C):
char *line = NULL;
size_t size = 0;
ssize_t nread;
while ((nread = getline(&line, &size, stdin)) != -1) {
// nread characters were read
do_stuff_with(line);
}
free(line);
If you don't have getline, you get to write your own (using getchar and realloc).

Insert a certain number of characters with spaces included

What I'm trying to accomplish is to take no more than "x" characters (spaces included) as input. I only know how to do both of them separately with scanf,
like the following:
scanf("%20s",str)
This takes no more than 20 characters.
scanf("%[^\n]s",str) takes spaces as well, but it has no limit.
I tried getline but it takes the \n as a value in the string as well and I don't want that. I hope I was clear enough about what I'm asking.
From what #chqrlie has told me I wrote this fuction:
void getstring(char *str, int len)
{
do
{
if (fgets(str, len, stdin))
{
fflush(stdin);
// if is not the first character to be the new line then change it to '\0' which is the end of the string.
if (str[0] != '\n')
str[strcspn(str, "\n")] = '\0';
}
}while (str[0] == '\n'); // Check if the user has inserted a new line as first character
}
The format for character classes does not have a trailing s, it is written this way:
scanf("%[^\n]", str)
If you wish to limit the maximum number of characters stored into the destination array, specify this number between the % and the [:
scanf("%20[^\n]", str)
Note however that the conversion will fail and scanf() will return 0 if there is an empty line pending for this conversion specification.
It is a common mistake to omit the test on the return value of scanf(), causing undefined behavior in case of conversion failures because the destination variables are left in their previous state (uninitialized in many cases).
It may be more effective to use fgets() and remove the trailing newline this way:
if (fgets(s, 20, stdin)) {
/* line was read, can be an empty line */
s[strcspn(s, "\n")] = '\0'; /* remove the trailing newline if any */
...
} else {
/* fgets() failed, either at end-of-file or because of I/O error */
...
}
You can use the following:
for(i = 0; i < x; i++)
{
getchar(c);
if(c == '\n') break;
str[i] = c;
}
But you must have to be aware of the existing newlines in the buffer. :)

How to scan a string with white spaces in structure members in C?

struct Demo{
char a[50];
char b[50];
int a;
};
Can anyone give the code for this structure Demo where a and b will contains string with different words[white-spaces].
I tried
scanf("[^\n]s",name.a); //where name is the object
fgets(name.a,50,stdin);
Note : we can't use gets method as well
So, If any other method is there, please provide me.
To read a line of user input into char a[50]; with its potential trailing '\n' trimmed:
if (fgets(name.a, sizeof name.a, stdin)) {
name.a[strcspn(name.a, "\n")] = '\0'; // trim \n
}
Work is needed to cope with consuming excessive long input lines and using the last element of name.a[] such as:
// Alternative
if (scanf("%49[^\n]", name.a) == 1) {
// consume trailing input
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
;
}
} else { // Handle lines of only \n, end-of-file or input error
name.a[0] = '\0';
}
The scanf("%49[^\n]%*c", name.a) approach has trouble in 2 cases:
1) The input is only "\n", nothing is saved in name.a and '\n' remains in stdin.
2) With input longer than 49 characters (aside from the '\n'), the %*c consumes an extra character, yet the rest of the long input line remains in stdin.
Both of these issues can be solves with additional code too.

Splitting scanf input into arrays until EOF

Looking to read in using scanf but I want to stop reading if I encounter a ',' '\0' (newline) or EOF
I'm not really sure how to stop achieve this.
I was using
char * aBuff;
char * bBuff;
char * cBuff;
//read in the first three lines and put them into char arrays
//while (scan() != (',' || '\0' || EOF)) //was trying to put it into a while loop, wasn't sure
scanf("%s", aBuff);
scanf("%s", bBuff);
scanf(%s, cBUff);
I plan on taking the input and putting them into separate arrays. Basically take input until a , or new line and place that data into an array and continue this process until the end of file.
scanf() is not a practical method to read until encountering ',', '\0', or EOF. Use fgetc().
The biggest problem is specifying '\0' in the format of scanf(). Example: with format "%[^,\0]", scanf() only reads "%[^," as it stops at the embedded '\0'. So with an invalid format specifier --> undefined behavior.
size_t ReadX(char *dest, size_t size) {
size_t len = 0;
if (size) {
while (--size > 0) {
int ch = fgetc(stdin);
if (ch == 0 || ch == ',' || ch == EOF) break; // maybe add \n too.
*dest[len++] = ch;
}
*dest[len] = '\0';
}
return len; // or maybe return the stopping ch
}
scanf() could be use if code used the ponderous:
scanf("%[\1\2\3...all_char_codes_min_char_to_max_char_except_,_and\0]%*c", &s);
You can try using scansets
scanf() should stop on EOF, but you'd want to maybe do something like this:
scanf("%[^,\0]", &s);

Resources