int main()
{
int n = 100;
char a[n];
char b[ ]="house";
fgets(a,n-1,stdin); // type "house"
if (strcmp(a,b) == 0)
printf("The strings are equal.\n");
else
printf("The strings are not equal.\n");
return 0;
}
Reason why this
if (strcmp(a,b) == 0) { }
is not true because fgets() stores the \n at the end of buffer. So here array a looks like house and array b looks like house\n(If ENTER key was pressed after entering input char's) and strcmp(a,b) doesn't return 0.
From the manual page of fgets()
fgets() reads in at most one less than size characters from stream
and stores them into the buffer pointed to by s. Reading stops
after an EOF or a newline. If a newline is read, it is stored
into the buffer. A terminating null byte ('\0') is stored after
the last character in the buffer.
One way is to use strcspn() which removes the trailing \n. For e.g
fgets(a,n,stdin);
a[strcspn(a, "\n")] = 0;
Now compare the char array like
if (strcmp(a,b) == 0) {
printf("The strings are equal.\n");
}
else {
printf("The strings are not equal.\n");
}
In your example, this is what strcmp is comparing
strcmp("house\n", "house")
Which is false.
Here is a solution you could add to fix your code to the way (I assume) you expect it to work.
int main()
{
int n = 100;
char a[n];
char b[] = "house";
fgets(a, n-1, stdin);
a[strlen(a) - 1] ='\0'; //you may want to add length checking to prevent errors if user input is null
if (strcmp(a, b) == 0)
printf("The strings are eq\n");
else
printf("Not eq\n");
return 0;
}
Related
I read chars until '\n', convert them to int and sum the numbers until the result is only one digit.
I can't use mod or .
The first run went well, but the second one keep running and not waiting to \n.
any reason for keeping the '\n'?
#include<stdio.h>
int main(){
char str[8], conv_str[8],c;
int i,val,ans = 0;
while(1){
printf("Enter 8 values(0-9) :\n");
scanf("%[^\n]", str); // Scan values to str untill \n
for(i = 0;i < 8;i++){
val = str[i]-48; //convert from asci to int
ans += val;
}
while(ans > 9){
// itoa convert int to string, str(the input) is the buffer and 10 is the base
itoa(ans,conv_str,10);
ans = (conv_str[0]-48) + (conv_str[1]-48) ;
}
printf("the digit is: %d", ans);
printf("\ncontinue? (y/n)\n");
scanf("%s", &c);
if (c == 'n')
break;
memset(str, 0, sizeof(str));
}
return 0;
}
TIA
You have multiple problems in the code. Some of them are
scanf("%s", &c); is wrong. c is a char, you must use %c conversion specifier for that.
You never checked for the return value of scanf() calls to ensure success.
While scanning for character input, you did not clear the buffer of any existing inputs. Any existing character, including a newline ('\n') already present in the buffer will be considered as a valid input for %c. You need to clear the buffer before you read a character input.
This is my code here, I'm trying to create a programme that counts characters using functions and then determine the average value of characters when an empty line is encountered. The programme is suppose to allow the user to enter multiple lines until an empty line is encountered but I can't seem to.
#include <stdio.h>
#include <Windows.h>
int main()
{
char str[1000];
int Digits, Char, SpecialChar, linecount = 0;
int counter;
int total;
int average;
Digits = Char = SpecialChar = 0;
printf("Please type in your words here: ");
gets(str);
for (counter = 0; str[counter] != NULL; counter++)
{
if (str[counter] >= '0' && str[counter] <= '9')
Digits++;
else if ((str[counter] >= 'A' && str[counter] <= 'Z') || (str[counter] >= 'a' && str[counter] <= 'z'))
Char++;
else
SpecialChar++;
}
while (str[counter] != '\n')
{
if (str[counter] = '\n')
{
linecount ++;
}
}
total = Digits + Char + SpecialChar;
average = total / linecount;
printf("\nDigits: %d \nCharacters: %d \nSpecial Characters: %d \nLine: %d", Digits, Char, SpecialChar, linecount);
printf("\nTotal no. of characters = %d", total);
printf("\nAverage no. of characters = %d", average);
Sleep(5000000);
return 0;
}
As far as I know, the function gets is interrupted after "\n". Also, using fgets you will have to put an attention on the '\0' addition on the string. That means that
The programme is suppose to allow the user to enter multiple lines until an empty line is encountered but I can't seem to.
will never be able to be accomplished using gets this way. Because gets is not a recommended function, I edited you code a little bit in a way that you might be searching.
Something to metion, that I found out it might be a logic error, before you read this code
for (counter = 0; str[counter] != NULL; counter++)
This seems strange, because the fgets will always record the "\n" character. So, the next condition
if (str[counter] = '\n')
will never be true
I see some others errors on you code, but, not majors ones. So, I see the suggestion as a sufficient as appointing them
while (fgets(str, 1000, stdin) && str[0] != '\n'){ //I dont know if checking the first element of the string is redundancy,
//because, the I think the fgets function will return NULL if you just press enter, as the first character
for (counter = 0; str[counter] != '\n'; counter++{
if (str[counter] >= '0' && str[counter] <= '9')
Digits++;
else if ((str[counter] >= 'A' && str[counter] <= 'Z') || (str[counter] >= 'a' && str[counter] <= 'z'))
Char++;
else
SpecialChar++;
}
linecount ++; //new line is someting that you will always reach, so,
//there is no reason for any condition
}
Solution is below:
#include <stdio.h>
#include <Windows.h>
int main()
{
char str[1000];
int Digits, Char, SpecialChar, linecount = 0;
int counter;
int total;
int average;
int flag = 1;
Digits = Char = SpecialChar = 0;
printf("Please type in your words here: ");
while(flag == 1)
{
gets(str);
if (str[0] == NULL || str[0] == '\n')
{
flag = 0;
break;
}
for (counter = 0; str[counter] != NULL; counter++)
{
if (str[counter] >= '0' && str[counter] <= '9')
Digits++;
else if ((str[counter] >= 'A' && str[counter] <= 'Z') || (str[counter] >= 'a' && str[counter] <= 'z'))
Char++;
else
SpecialChar++;
}
linecount ++;
}
total = Digits + Char + SpecialChar;
average = total / linecount;
printf("\nDigits: %d \nCharacters: %d \nSpecial Characters: %d \nLine: %d", Digits, Char, SpecialChar, linecount);
printf("\nTotal no. of characters = %d", total);
printf("\nAverage no. of characters = %d", average);
Sleep(5000000);
return 0;
}
The gets() function is unsafe and extremely susceptible to buffer overflows. Never use this function. A better alternative is fgets(), though the non-standard (but widely available) POSIX getline() function is also a good option.
Both fgets() and gets() fetch a line of input, but gets() discards the newline character, while fgets() keeps it and stores it in the input buffer (if there is room). This means that you may need to remove the newline character after fetching a line of input with fgets(). It also means that when the user simply presses ENTER, the input buffer contains only a \n character, followed by a \0 null terminator; fgets() always null-terminates the input buffer.
To read multiple lines of user input, stopping only when the user presses ENTER, fgets() should be called in a loop. One way of doing this is to use a for(;;) {} loop construction, which never terminates (equivalent to while(1) {}). If the first character in a line of input is a \n character, then a break; statement exits the loop.
Notes on the Posted Code
The posted code is comparing input characters with character constants to determine whether the input is numeric, alphabetic, or otherwise. This is better, and more portably, accomplished by using Standard Library functions from ctype.h. Using library functions here means that the code does not need to explicitly consider the current locale or character encoding (which may not be ASCII or UTF-8).
The posted code contains the line:
for (counter = 0; str[counter] != NULL; counter++) {}
Note that NULL is the null pointer constant, equivalent to (void *) 0, but not equivalent to 0. The goal of this loop appears to be to iterate over a string, terminating when the null terminator (\0) is reached. So, the controlling expression should be changed:
for (counter = 0; str[counter] != '\0'; counter++) {}
Also, the purpose of this loop in the posted code is unclear:
while (str[counter] != '\n')
{
if (str[counter] = '\n')
{
linecount ++;
}
}
If str[counter] is a newline character, then the loop is not entered; otherwise the if statement in the loop body assigns '\n' to str[counter], evaluating to true and incrementing linecount. On the next iteration str[counter] == '\n', so the loop is terminated. After the previous loop (with NULL changed to '\0' in the controlling expression), counter is the index of the \0 character in str, so this loop replaces the null terminator with a newline character, making str a string no longer. This will lead to undefined behavior if the code later attempts to treat str as a string.
If the line if (str[counter] = '\n') is a typo, meant to be if (str[counter] == '\n'), then this is an infinite loop once entered.
An Example Program
Here is a heavily modified of the posted code that uses fgets() to get user input, and Standard Library functions to classify input characters.
The fgets() function returns a null pointer in the event of an error, so this is checked for and handled in about the simplest way possible. After input has been stored in the str[] buffer array, the first character is checked; if it is \n, then the user entered an empty line (probably: see the next paragraph), and the loop is terminated. Otherwise, the next step is to see if the input line contains a newline character at all. The strchr() (from string.h) function is used here for this. If the \n is not found, then a null pointer is returned, otherwise a pointer to the \n character is returned. This is used to write over the \n with \0, effectively removing the newline character. Then linecount is incremented. Thus, the line counter is incremented only when a newline character is encountered in the input.
Note that when input is too large for the input buffer, at least the newline character will remain in the input stream waiting for the next I/O function call. It is possible that only the newline character remains in the input stream, so on the next loop iteration the first character in the buffer is \n, interpreted by this program as an empty line. If there is a possibility that input will be larger than the buffer allocation, more subtlety will be required to handle this situation. One solution is to use a flag to indicate whether the start of a line is being read. Here, line_start is initialized to 1, set to 1 whenever linecount is incremented, and set to 0 whenever a newline character is not found in the input buffer. In order for a newline to indicate an empty line of input, line_start must be set to 1, and the first character in the input buffer must be a \n character. With this modification, the program will reliably read lines of input even longer than the allocated 1000 characters. You can test this out by making the allocation for str[] smaller; try char str[2];.
Here is the complete program:
#include <stdio.h>
#include <ctype.h> // for isdigit(), isalpha()
#include <string.h> // for strchr()
int main(void)
{
char str[1000];
int Digits = 0;
int Char = 0;
int SpecialChar = 0;
int linecount = 0;
int counter;
int total;
int average;
puts("Please type in your words here:");
int line_start = 1;
for (;;) {
if (fgets(str, sizeof str, stdin) == NULL) {
/* Handle error */
fprintf(stdin, "I/O error\n");
return 1;
}
/* Terminate loop on empty line */
if (line_start && str[0] == '\n') {
break;
}
/* If newline present, remove and increment linecount */
char *cptr = strchr(str, '\n');
if (cptr != NULL) {
*cptr = '\0';
++linecount;
line_start = 1;
} else {
line_start = 0; // complete line not read
}
/* update character counters */
for (counter = 0; str[counter] != '\0'; counter++) {
unsigned char uc = str[counter];
if (isdigit(uc)) {
Digits++;
} else if (isalpha(uc)) {
Char++;
} else {
SpecialChar++;
}
}
}
total = Digits + Char + SpecialChar;
average = total / linecount; // integer division
printf("Digits: %d \nCharacters: %d \nSpecial Characters: %d \nLine: %d\n",
Digits, Char, SpecialChar, linecount);
printf("Total no. of characters = %d\n", total);
printf("Average no. of characters = %d\n", average);
return 0;
}
I created function that takes in a char pointer. I first get the string value from fgets, the input i'm entering is "rwx". When I enter that value, the strlen of it says it's length is 2 and when I look at the first index of the char array, it returns rw instead of r. May I ask where abouts am I going wrong for iterating through the string?
What I've tried:
int main()
{
char access[3];
while (ValidateAccess(access))
{
printf("Please enter your access\n");
fgets (access, 3, stdin);
}
return 0;
}
int ValidateAccess(char * access)
{
int length = strlen(access);
int r = 0,w = 0,x = 0,i;
printf("this is the length %d\n", length);
if (length == 0)
return 1;
for(i = 0; i < length; i++)
{
printf("this is the character: %s", &access[i]);
if (strcmp(&access[i], "r") == 0)
r++;
else if (strcmp(&access[i], "w") == 0)
w++;
else if (strcmp(&access[i], "x") == 0)
x++;
}
if (r <=1 && w <= 1 && x <= 1 )
return 0;
else
return 1;
}
when the program is ran this is the output
"this is the length 0"
Please enter your access
rwx
this is the length 2
this is the character: rw
man fgets is a very useful reading. Let me quote: "fgets() reads in at most one less than size characters from stream..."
The strings in C are expected to be terminated with \0 (zero byte). When you define access as an array of 3 elements, it has a room for a string of length 2 -- two characters plus terminating zero byte. When you call fgets saying that you have the space for 3 bytes, it reads two characters, puts them in the first two bytes, and puts terminating zero in the third byte.
Define access a having 4 bytes, and pass 4 to fgets.
Additionally, you are printing string not a char, so it prints everything to the terminating zero byte (that's where rw you see comes from). If you want to print a single character, use %c in format string, not %s (and you should pass a character, not a pointer then).
Try the following program and make sure you understand the output.
#include <stdio.h>
int main() {
char *foo = "barbaz";
printf("%c\n", foo[2]);
printf("%s\n", foo + 2);
}
How can I scanf() the integer values I enter into an array until I hit enter.
I believe I can use getchar() != '\n'.
but how do I loop through the line ?
Suppose my input is 20 21 2 12 2. I want an array that has all those inputs.
What given functions could I use in order to scan them all in.
You are trying to read integers as characters so once read you need to convert it to integers.
Read the line to a buffer using fgets() then parse the input buffer to get integers.
Store the integers to the array.
The code looks like
char buf[300];
int a[5],i=0;
fgets(buf,sizeof(buf),stdin);
char *p = strtok(buf," ");
while(p != NULL)
{
char *endptr;
a[i] = strtol(p,&endptr,10);
if ((*endptr != '\0') && (isspace(*endptr) == 0))
printf("warning: invalid value detected\n");
else
i++;
p = strtok(NULL," ");
}
You can use the alternative strtol() instead of atoi() to convert string to integer.
PS: Your buf should be large enough to hold the whole line. fgets() read till newline character.
If you use getchar() you obtain digits one by one, so you need
to store them first in the buffer, and when white space comes,
you convert those digits into a number, and store it into array.
here is the explanation of the code I made for you.
1st if statement : if obtained character is a digit, store it in buf
2nd if statement : if obtained character is a white space or EOL and at least 1 digit is stored in buf, convert digits into number and store it in array a.
3rd if statement : if obtained character is not a digit or a white space or a EOL, warns users.
4th if statement : if obtained character is a EOL, end loop.
The code below works fine.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(){
#define BUFSIZE 50
#define ARRAYSIZE 5
int i,k,a[ARRAYSIZE];
char c,buf[BUFSIZE];
for(i=0,k=0;(i<BUFSIZE)&&(k<ARRAYSIZE);){
c=getchar();
if(isdigit(c)){
buf[i++] = c;
}else if((i>0) && (c==' ' || c=='\n')){
buf[i] = '\0';
a[k++] = atoi(buf);
i=0;
}else if(!(c==' ' || c=='\n')){
printf("warning : invalid value %c is detected\n",c);
i=0;
}
if(c=='\n'){
break;
}
}
printf("input :");
for(i=0;i<ARRAYSIZE;i++){
printf("%d, ",a[i]);
}
printf("\n");
}
In this program I have taken a dimensional character array of size[3][4],
as long as I enter a 3 characters for each row it will work well.
For example: if I enter abc abd abd I get the same output but if i enter more letters in the first or second or 3rd row I get an error.
How should I check for null character in 2 dimensional?
# include <stdio.h>
#include <conio.h>
# include <ctype.h>
void main()
{
int i=0;
char name[3][4];
printf("\n enter the names \n");
for(i=0;i<3;i++)
{
scanf( "%s",name[i]);
}
printf( "you entered these names\n");
for(i=0;i<3;i++)
{
printf( "%s\n",name[i]);
}
getch();
}
As pointed out by #SouravGhosh, you can limit your scanf with "%3s", but the problem is still there if you don't flush stdin on each iteration.
You can do this:
printf("\n enter the names \n");
for(i = 0; i < 3; i++) {
int c;
scanf("%3s", name[i]);
while ((c = fgetc(stdin)) != '\n' && c != EOF); /* Flush stdin */
}
How should I chk for null character in 2 dimensional ... [something has eaten the rest part, I guess]
You don't need to, at least not in current context.
The problem is in your approach of allocating memory and putting input into it. Your code has
char name[3][4];
if you enter more that three chars, you'll be overwriting the boundary of allocated memory [considering the space of \0]. You've to limit your scanf() using
scanf("%3s",name[i]);
Note:
change void main() to int main(). add a return 0 at the end.
always check the return value of scanf() to ensure proper input.
EDIT:
As for the logical part, you need to eat up the remainings of the input words to start scanning from the beginning of the next word.
Check the below code [Under Linux, so removed conio.h and getch()]
# include <stdio.h>
# include <ctype.h>
int main()
{
int i=0; char name[3][4];
int c = 0;
printf("\n enter the names \n");
for(i=0;i < 3;i++)
{
scanf( "%3s",name[i]);
while(1) // loop to eat up the rest of unwanted input
{ // upto a ' ' or `\n` or `EOF`, whichever is earlier
c = getchar();
if (c == ' ' || c == '\n' || c == EOF) break;
}
}
printf( "you entered these names\n");
for(i=0;i<3;i++)
{
printf( "%s\n",name[i]);
}
return 0;
}
(Cringing after reading the answers to date.)
First, state the problem clearly. You want to read a line from stdin, and extract three short whitespace separated strings. The stored strings are NUL terminated and at most three characters (excluding the NUL).
#include <stdio.h>
void main(int, char**) {
char name[3][4];
printf("\n enter the names \n");
{
// Read tbe line of input text.
char line[80];
if (0 == fgets(line, sizeof(line), stdin)) {
printf("Nothing read!\n");
return 1;
}
int n_line = strlen(line);
if ('\n' != line[n_line - 1]) {
printf("Input too long!\n");
return 2;
}
// Parse out the three values.
int v = sscanf(line, "%3s %3s %3s", name[0], name[1], name[2]);
if (3 != v) {
printf("Too few values!\n");
return 3;
}
}
// We now have the three values, with errors checked.
printf("you entered these names\n%s\n%s\n%s\n",
name[0], name[1], name[2]
);
return 0;
}
you might consider something on the order of scanf( "%3s%*s",name[i]);
which should, if I recall correctly, take the first three characters (up to a whitespace) into name, and then ignore anything else up to the next white space. This will cover your long entries and it does not care what the white space is.
This is not a perfect answer as it will probably eat the middle entry of A B C if single or double character entries are mode. strtok, will separate a line into useful bits and you can then take substrings of the bits into your name[] fields.
Perhaps figuring out the entire requirement before writing code would be the first step in the process.