How do I check length of user input in C? - c

I'm kind of new to C, and the input reading is really confusing me. I'm trying to initialize an array of size 4, but sometimes the user will enter valid input of 3. In Java, I could check the length of the input and add conditionals, but I'm not sure how this works in C.
main(void){
char str[N];
int i;
for(i = 0; i < N; i++){
scanf("%c", &str[i]);
}
for(i = 0; i < N; i++){
printf("%c\n", str[i]);
}
}
Right now, if I input 4 or more, it works fine. If I input 3, it breaks. I'd like it to handle both 3 or 4 characters.
Actually, the root of the problem is: I'm trying to figure out a way in C to read in a 24-hour-clock time, and add it to a 24-hour-clock duration. Should I be approaching this an entirely different way?
Thanks,

The short answer is: you can't.
Using scanf() is particularly dangerous because of this if you want to read in a string (%s); if the user enters more input than your buffer can hold, you have a buffer overflow on your hands.
fgets() on the other hand, allows you to specify the max number of bytes you will read, preventing you from overflowing the buffer.
Here's a quick example on how you'd write a function for some input that verified that the input was within a specified length and was a complete line (ending with \n - this routine discards the \n from the input):
void getInput(char *question, char *inputBuffer, int bufferLength)
{
printf("%s (Max %d characters)\n", question, bufferLength - 1);
fgets(inputBuffer, bufferLength, stdin);
if (inputBuffer[strlen(inputBuffer) -1] != '\n')
{
int dropped = 0;
while (fgetc(stdin) != '\n')
dropped++;
if (dropped > 0) // if they input exactly (bufferLength - 1)
// characters, there's only the \n to chop off
{
printf("Woah there partner, your input was over the limit by %d characters, try again!\n", dropped );
getInput(question, inputBuffer, bufferLength);
}
}
else
{
inputBuffer[strlen(inputBuffer) -1] = '\0';
}
}
int main()
{
char firstAnswer[10];
getInput("Go ahead and enter some stuff:", firstAnswer, 10);
printf("Okay, I got: %s\n",firstAnswer);
}

scanf() allows the use of maximum width specifiers:
So scanf("%3s", buffer) reads at most 3 characters + 1 NUL terminator.

Related

String Input with multiple lines

int main() {
char userInput[100]; //Store user input
//Take user input
//scanf(" %s",&userInput);
//scanf("%[^\n]s",&userInput);
//scanf("%[^\n]", &userInput);
//gets(userInput);
scanf("%[]s", &userInput); //This takes input but doesnt leave input loop
printf(" %s",userInput);
//i = index to start for looping through the string, starting at the beginning
//count = Stores occurrences of '$'
//inputLength = length of the input, used for limit of loop
int i =0,count =0;
int inputLength = strlen(userInput);
//Loop through the user input, if the character is '$', the integer count will be incremented
for (i; i < inputLength; i++){
if (userInput[i] == '$'){
count++;
}
}
printf("%d", count);
return 0;
}
Hi i'm having some issues with my code, i need to take an input of 3 lines and count the number of'$' in the input. The input method not commented "scanf("%[]s", &userInput);" is the one only i have discovered to take all 3 lines of input, BUT i can't break the input loop and continue with my program.
Any help would be greatly appreciateed
To read 3 lines with the cumbersome scanf(), code needs to look for '$', '\n', and EOF. The rest of input is discardable.
int count = 0;
int line = 0;
while (line < 3) {
scanf("%*[^$\n]"); // Scan for any amount of characters that are not $ nor \n,
// "*" implies - do not save.
char ch;
if (scanf("%c", &ch) != 1) { // Read next character.
break;
}
if (ch == '$') count++;
else line++;
}
printf("$ count %d\n", count);
As #chux suggested, reading with fgets provides a convenient way to protect from buffer overrun and without having to hard code field-width modifiers in scanf conversion specifiers.
Here, if all you need to do is count the number of '$' characters found in your input (regardless of how many lines), you can simply read ALL the input in fixed sized chunks of data. fgets does just that. It doesn't matter if you have one line, or one million lines of input. It also doesn't matter if your input lines are one-character or one million characters long. You can simply read each line and count the number of '$' found within each chunks of data read, keeping a count of the total found.
You can do this for any character. If you wanted to also count the number of line, you can simply check for '\n' characters and keep a total there as well. The only corner-case in counting lines with fgets is to insure you protect against a non-POSIX end-of-file (meaning a file with no '\n' as the final character). There are a couple of ways to handle this. Checking that the last character read was a '\n' is as good as any.
Putting the pieces together, and protecting against a non-POSIX eof, you could do something similar to the following, which simply reads all data available on stdin and outputs a final '$' and line count:
#include <stdio.h>
#define MAXC 100
int main (void) {
char buf[MAXC] = ""; /* buffer to hold input in up to MAXC size chunks */
size_t lines = 0, dollars = 0; /* counters for lines and dollar chars */
int i = 0;
while (fgets (buf, MAXC, stdin)) /* read all data */
for (i = 0; buf[i]; i++) /* check each char in buf */
if (buf[i] == '$') /* if '$' found */
dollars++; /* increment dollars count */
else if (buf[i] == '\n') /* if '\n' found */
lines++; /* increment line count */
if (i && buf[i-1] != '\n') /* protect against non-POSIX eof */
lines++;
/* output results */
printf ("input contained %zu lines and %zu '$' characters.\n",
lines, dollars);
return 0;
}
Look things over and let me know if you have further questions.
scanf("%[]s", &userInput);" is the one only i have discovered to take all 3 lines of input, BUT i can't break the input loop and continue with my program.
"%[]" is an invalid scanf() specifier. Anything may happen, it is undefined behavior, including taking all lines in and not returning.
The 's' in the format serves no purpose here - drop it.
Yes fgets() is best but let us abuse scanf() to read 3 lines and look for '$'.
char line[3][100] = {0};
// v--------- Consume all leading whitespace
// | vv ----- limit input to 99 characters as scan() appends a \0
// | || v-v-- Look for "not \n"
#define FMT_1LINE " %99[^\n]"
// Let the compiler concatenate the 3 formats into 1 string for scanf
int scan_count = scanf(FMT_1LINE FMT_1LINE FMT_1LINE, line[0], line[1], line[2]);
// Check return value
if (scan_count == 3) {
// Successfully read 3 lines
int count = 0;
for (int line_index = 0; line_index < 3; line_index++) {
char *s = line[line_index];
while (*s) { // no need for strlen(), just loop until the null character
count += *s == '$';
s++;
}
}
printf("$ count %d\n", count);
}
You write:
scanf("%[]s", &userInput); //This takes input but doesnt leave input loop
but the comment is at best misleading. Your format string is malformed, so the behavior of the scanf call is undefined. An empty scan set (between the [] in the format) does not make sense, because the resulting field could never match anything. Therefore, a ] appearing immediately after the opening ] of the scan set is interpreted as a literal character not the ending delimiter. Your scan set is therefore unterminated.
Note, too, that %[ is its own field type, separate from %s. An 's' following the closing ] of the scan set is not part of such a field descriptor, but rather an ordinary character to match.
A trivial way to do this with scanf would be to read characters one at a time in a loop via a %c field. This is probably not what the exercise is looking for, and it's a hack to use scanf() instead of getchar() for this purpose, but perhaps it would serve:
int nl_count = 0;
int dollar_count = 0;
do {
char c;
int result = scanf("%c", &c);
if (result != 1) {
break;
}
switch (c) {
case '\n':
nl_count++;
break;
case '$':
dollar_count++;
break;
}
} while (nl_count < 3);
I'm afraid it would be much more complicated to do it safely reading multiple characters at a time with a %[ field, and there is no safe way to read all three lines in one scanf call, unless you can rely on the input lines not to exceed a line length limit known to you.
int readMatrix() {
char userInput[100][3]; //Store user input
int j = 0, m = 0;
for(m = 0; m < 3; m++){
scanf("%s", &userInput[j][m]); //This takes input (Ex: 22 *(enter)* 33$ *(enter)* 66$ *(enter)*
j++; //increase the column
}
int i =0,count =0;
m = 0;
//Loop through the user input, if the character is '$', the integer count will be incremented
for (i = 0; i < 100; i++){
for(m = 0; m < 3; m++){
if (userInput[i][m] == '$'){
count++;
}
}
}
printf("%d", count);
return 0;
}

C program Need help fixing my code for a word sort program

Hi I am still new to c and have been working on this word sort program for some time now. the guidelines are:
Write a program that sorts a series of words entered by the user. Assume that each word is no more than 20 characters long. Stop reading when the user enters an empty word. Store each word in a dynamically allocated string, using an array of pointers (use the read_line function). After all lines have been read sort the array. Then use a loop to print the words in sorted order.
The problem I seem to be having is that the program will accept words but when I enter the empty word it goes to a new line and nothing happens. An help or advice would be greatly appreciated. here is my code so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 20
#define LIM 20
int read_line(char str[], int n);
void sort_str(char *list[], int n);
int alpha_first(char *list[], int min_sub, int max_sub);
int main(void)
{
char *list[LIM];
char *alpha[LIM];
char word_str[LEN];
int word, i, j, num_count = 0;
for(;;){
printf("Enter a word: ");
scanf("%s", &word);
if(word == NULL)
break;
else
read_line(word_str, LEN);
list[i] = malloc(strlen(word_str) + 1);
strcpy(list[i], word_str);
alpha[i] = list[i];
}
sort_str(alpha, i);
for(i = 0; i < num_count; ++i){
printf("Sorted: ");
puts(list[i]);
}
return (0);
}
int read_line(char str[], int n)
{
int ch, i = 0;
while ((ch = getchar()) != '\n')
if (i < n)
str[i++] = ch;
str[i] = '\0';
return i;
}
void sort_str(char *list[], int n)
{
int i, index_of_min;
char *temp;
for (i= 0; i < n - 1; ++i) {
index_of_min = alpha_first(list, i, n - 1);
if (index_of_min != i) {
temp = list[index_of_min];
list[index_of_min] = list[i];
list[i] = temp;
}
}
}
int alpha_first(char *list[], int min_sub, int max_sub){
int i, first;
first = min_sub;
for(i = min_sub + 1; i <= max_sub; ++i){
if(strcmp(list[i], list[first]) < 0){
first = i;
}
}
return (first);
}
Your logic flow is flawed. If a word is entered, the scanf() will eat it from stdin and store a null-terminated string at the address of the integer 'word'. Any more than 3/7 chars entered, (32/64 bit, allowing for the null terminator), will start corrupting the stack. read_line() will then only have the line terminator to read from stdin, (assuming the UB doesn't blow it up first).
The problem I seem to be having is that the program will accept words but when I enter the empty word it goes to a new line and nothing happens.
There are several problems with this:
char word_str[LEN];
int word, i, j, num_count = 0;
/* ... */
scanf("%s", &word);
if(word == NULL)
break;
First, scanf("%s", &word) scans whitespace-delimited strings, and to that end it skips leading whitespace, including newlines. You cannot read an "empty word" that way, though you can fail to read a word at all if the end of the input is reached (or an I/O error occurs) before any non-whitespace characters are scanned.
Second, you are passing an inappropriate pointer to scanf(). You should pass a pointer to a character array, but you instead pass a pointer to an int. It looks like maybe you wanted to scan into word_str instead of into word.
Third, your scanf() format does not protect against buffer overflow. You should provide a field width to limit how many characters can be scanned. Moreover, you need to be sure to leave room for a string terminator.
Fourth, you do not check the return value of scanf(). If it fails to match any characters to the field, then it will not store any. Since it returns the number of fields that were successfully scanned (or an error indicator), you can detect this condition.
One way to correct the scanf() and "empty word" test would be:
int result;
result = scanf("%*[ \t]%19[^ \t\n]", word_str);
if (result < 1) break;
(That assumes a fixed maximum word length of 19 to go with your declared array length of 20.) You have several additional problems in your larger code, large among them that read_line() attempts to read the same data you just read via scanf() (in fact, that function looks altogether pointless). Also, you never update num_count, and after calling sort_str() you lose track of the number of strings you've read by assigning a new value to variable i.
There may be other problems, too.

Assign null string to gets

I want to write a program in C that fills an array p[MAX][N] of strings
I used this but i dont know which is the null string to enter when i give input.
#include <stdio.h>
#include <string.h>
#define R 3
#define C 8
int main()
{
int i;
char strings[R][C];
printf("***Table of Strings - Names***\n\n");
for(i=0;(i<R && gets(strings[i]));i++)
;
if(i==R)
printf("\n**Table Full - input terminated \n");
for(i=0;i<R;i++)
puts(strings[i]);
return 0;
}
First, never use gets(). It is inherently dangerous as it doesn't do any bounds checking on the memory you pass to it. Use fgets() instead:
for (i = 0; i < R && fgets(strings[i], C, stdin); ++i);
Note that fgets() will leave any new line ('\n') in the input at the end of the string, assuming that the whole line can fit in your buffer. If the whole line can't fit in your buffer, then it reads as much as can fit into your buffer (leaving room for and always appending a nul terminator), stops reading the input at that point and leaves the rest of the input on the stream. With C being so small in your program, such an occurrence is quite likely.
Alternatively, you could use getline() if it's available on your platform:
char *strings[R] = { 0 };
size_t cap;
for (i = 0; i < R && 0 <= getline(&strings[i], (cap = 0, &cap), stdin));
if (i == R)
printf("\n**Table Full - input terminated \n");
for (i = 0; i < R && strings[i]; ++i)
puts(strings[i]);
/* program done; clean up strings */
for (i = 0; i < R && strings[R]; ++i)
free(strings[R]);
getline() automatically dynamically (re)allocates the memory necessary to fit the next line from the input stream. It also leaves any new line ('\n') in the input at the end of the string.
Second, ctrl-D is typically used terminate the input to a program from a terminal.
It worked. I changed it to this
int main()
{
int i,j,max,thesi,sum=0,countCH=0,mikos=0;
char strings[R][C];
printf("***Table of Strings - Names***\n\n");
for(i=0;(i<R && fgets(strings[i],C,stdin ));i++)
;
if(i==R)
printf("\n**Table Full - input terminated \n");
for(i=0;i<R;i++)
fputs(strings[i],stdout);
//Euresh megistou string
max=0;
sum=0;
for(i=0;i<R;i++)
{
mikos=strlen(strings[i])-1;
sum+=mikos;
if(mikos>max)
{
max=mikos;
thesi=i;
}
}
printf("\nTo string me to megalitero mikos einai auto pou brisketai sthn %d seira \nkai einai to %s \nme mhkos %d",thesi+1,strings[thesi],max);
printf("\nO pinakas me ta strings periexei %d xaraktires\n",sum);
return 0;
}
It works just fine only that strlen counts all the chars of the string including null char why is that i dont get it?

fread is terminating before accepting all user inputs(from stdin)

Here is a solution to a CODECHEF Problem "INTEST", which basically tests how fast IO operation is done by a code.
Input
The input begins with two positive integers n k (n, k<=107). The next n lines of input contain one positive integer ti, not greater than 109, each.
Output
Write a single integer to output, denoting how many integers ti are divisible by k.
The following code segment is the fastest C Code submitted so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 65535
int main(int argc, char *argv[])
{
char buffer[SIZE];
unsigned long n, k, input, count;
int c, i;
count = 0;
scanf("%lu %lu\n", &n, &k);
input = 0;
while ((c = fread (buffer, sizeof (char), SIZE, stdin)) > 0)
{
for (i = 0; i < c; i++)
{
if (buffer[i] == '\n')
{
//printf("%d\n", input);
if ((input % k) == 0)
{
count++;
}
input = 0;
}
else
{
input = (input * 10) + (buffer[i] - '0');
}
}
}
printf("%lu\n", count);
return 0;
}
They said that fread() offers a faster IO than scanf as fread() does a buffer IO. But when I compile and run it on my own computer(CODEBLOCKS) and give it a few inputs from the console[Note: I am not piping the input file], suppose I enter 4 3 on the first line denoting that 4 more lines follow. But fread() is not even bothering to accept the 4 more lines and after taking one more input basically the program outputs a 0 if I enter a number divisible by 3 or 1 if the number enter is not divisible by 3 and just terminates.
Why is fread() terminating before accepting all the inputs?
In case of file IO, we can be sure that fread() will read until buffer is full or a file terminator is encountered. But in case of stdin, how long will fread() wait for the user to enter inputs?
Why the program is using a buffer of SIZE 65536?
When the input comes from a terminal, the terminal driver hands data over after each line, and fread() only returns what's available. After the scanf(), the first call to fread() will likely return just one byte, the newline left behind by scanf(). Thereafter, each call will read a single line, because that's the way the terminal driver works.
By contrast, if the input is a regular file, then the fread() call will return as many characters as are available, up to the size of the buffer, completely ignoring newlines as special cases.
If the input is a pipe, then it will read what is available in the pipe at any given time, which might or might not be multiple lines of data, depending on how it is written and whether the reading code keeps up with the writing code.
#include<stdio.h>
int main(){
int i,n,k,m[50],count;
printf(" ");
scanf("%d %d",&n,&k);
count=0;
for(i = 1; i <= n; i++){
printf(" \n");
scanf("%d",&m[i]);
if(m[i] % k==0){
count=count + 1;
}
}
printf("ans=%d",count);
return 0;
}`enter code here`

Counting characters in C

I'm trying to write a program that counts all the characters in a string. I originally had it, but then realized I can't count spaces. I can't see why this does not work.
for(m=0; z[m] != 0; m++) {
if(z[m] != ' ') {
charcount ++;
}
}
Any assistance appreciated.
Edit* Does it make a difference if the input(strings) are being scanned in like this? And yes, everything is initialized. I've tried printing what z[m] evaluates too and it isn't the actual value of the string at "m", I think this is the problem.
for(j=0; j<7; j++){
printf("Enter a string:\n");
scanf("%s", z);
for(m=0; z[m] != 0; m++){
if(z[m] != ' '){
charcount ++;
}
}
You need to initialize charcount. Other than that, it should work, provided that z is a zero-terminated array of characters and m is an int or similar. I would probably write just z[m] rather than z[m] != 0 (since !0 = true and 0 = false), but both work. There are more efficient ways of doing it (although these days I bet a compiler will handle converting this into a pointer-based loop for you).
Here's a complete, correct example with minimal edits:
const char * z = "testing one two three";
int m;
int charcount;
charcount = 0;
for(m=0; z[m]; m++) {
if(z[m] != ' ') {
charcount ++;
}
}
If you're using a String class of some kind rather than an old-fashioned C null-terminated array, you'll want to look at that class for how to loop through it.
All of the above also assumes you're dealing with ASCII strings. If you're dealing with UTF-encoded strings, you have to handle multi-byte characters.
Re your edit: It makes a big difference: scanf will stop on the first blank (I'd forgotten that). It might make an even bigger difference than that, though, if you're not declaring z correctly. (I'd also recommend using a field width when using scanf for reading strings [or avoiding scanf entirely]; otherwise, you have no control over the number of chars it will try to store, and so in theory, no buffer will ever be big enough to avoid an overflow. More here: http://www.crasseux.com/books/ctutorial/String-overflows-with-scanf.html)
You can use strlen()
I'd suggest using a while loop, and to use more meaningful variable names
m = textIndex
z = text
Something like this would work
while (text[textIndex] != 0x00)
{
textIndex++;
}
Instead of using scanf, try fgets like so:
char input[256];
fgets(input, sizeof(input), stdin);
fgets will read an entire line from a file. As such, passing stdin as the file handle will make it read from standard input, which in most cases will be bound to the console. One thing to watch out for, though, is that the string you get from fgets might include the newline character. Rather than explicitly checking your strings for inequality with the space character (' '), I suggest using the isspace function from ctype.h, which will check for various forms of whitespace (including a regular space and newline).
Here is a complete, runnable example:
#include <stdio.h>
#include <ctype.h>
int count_nonspace(const char* str)
{
int count = 0;
while(*str)
{
if(!isspace(*str++))
count++;
}
return count;
}
int main()
{
char input[256];
fgets(input, sizeof(input), stdin);
printf("%d\n", count_nonspace(input));
}
Yes, there is a difference on input-scan with scanf:
scanf("%s", z);
...
if(z[m] != ' '){
scanf("%s"...) always breaks at space-character, therefore your if ever is true. Better you use fgets to read from stdin,
#define MAXINPUT 80
char line[MAXINPUT];
for(j=0; j<7; j++) {
printf("Enter a string:\n");
if( fgets( line, 80, stdin ) )
{
char *c=line;
if( strchr(line,'\n') ) *strchr(line,'\n')=0;
while( *c )
{
if( *c!=' ' )
++charcount;
++c;
}
}
}
Or if you want WHITE -spaces then take
#include <ctype.h>
...
if( !isspace(*c) )
this seems to work for me, its a simple 30 line code that is in a loop and can detect the letter of choice for the chosen string/sentence/word the user has inputted.
#include <stdio.h>
#include <string.h>
int main(){
while(true){
char string[100];
char letter[100];
int count = 0;
printf("Enter a word/sentence:\n");
scanf(" %[^\n]s",string);
printf("Enter a letter:\n");
scanf(" %c",&letter); //when using scanf for a sentence/word or character, always include a space afterwards.
//Counts each character except space
for(int i = 0; i < strlen(string); i++) {
if(string[i] == letter[0]){
count++;
}
}
//Displays the total number of characters present in the given string
printf("Total number of characters in the string: %d\n", count);
printf("%s\n",string);
}
return 0;
}

Resources