Trying to count the number of 'a' that are entered - character

Whenever I try to run the following code to count my characters I constantly get zero instead of the number of characters I have inserted.
#include <stdio.h>
void main() {
int c;
int count = 0;
while ( (c = getchar() != EOF) && c == 'a' ) {
count = count +1;
}
printf("Number of chara: %d", count);
}
I have altered the code to instead only count whenever 'a' comes up, but still only get zero when I enter my characters and hit the return key.

The condition of your while loop evaluates to false when the program reads a character that isn't an 'a', which ends the while loop. Since your program reads characters in the while loop, no more characters get read.
Try checking if the character is an 'a' inside the loop body before updating the counter instead of in the loop condition.

The loop will stop because you set the c=='a'. Try to remove that in your code.
Try this one:
int c;
int count = 0;
while (c = getchar() != EOF ) {
count = count +1;
}
printf("Number of chara: %d", count);
}`

Related

C question in logical OR: 2 operands evaluated (0) false, but the result works as TRUE range

My doubt is about the basic theory of "or logical operator". Especifically, logical OR returns true only if either one operand is true.
For instance, in this OR expression (x<O || x> 8) using x=5 when I evalute the 2 operand, I interpret it as both of them are false.
But I have an example that does not fit wiht it rule. On the contrary the expression works as range between 0 and 8, both included.
Following the code:
#include <stdio.h>
int main(void)
{
int x ; //This is the variable for being evaluated
do
{
printf("Imput a figure between 1 and 8 : ");
scanf("%i", &x);
}
while ( x < 1 || x > 8); // Why this expression write in this way determinate the range???
{
printf("Your imput was ::: %d ",x);
printf("\n");
}
printf("\n");
}
I have modified my first question. I really appreciate any helpo in order to clarify my doubt
In advance, thank you very much. Otto
It's not a while loop; it's a do ... while loop. The formatting makes it hard to see. Reformatted:
#include <stdio.h>
int main(void) {
int x;
// Execute the code in the `do { }` block once, no matter what.
// Keep executing it again and again, so long as the condition
// in `while ( )` is true.
do {
printf("Imput a figure between 1 and 8 : ");
scanf("%i", &x);
} while (x < 1 || x > 8);
// This creates a new scope. While perfectly valid C,
// this does absolutely nothing in this particular case here.
{
printf("Your imput was ::: %d ",x);
printf("\n");
}
printf("\n");
}
The block with the two printf calls is not part of the loop. The while (x < 1 || x > 8) makes it so that the code in the do { } block runs, so long as x < 1 or x > 8. In other words, it runs until x is between 1 and 8. This has the effect of asking the user to input a number again and again, until they finally input a number that's between 1 and 8.

strncpy functions produces wrong file names

I am new in C and writing a code to help my data analysis. Part of it opens predetermined files.
This piece of code is giving me problems and I cannot understand why.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLOGGERS 26
// Declare the input files
char inputfile[];
char inputfile_hum[MAXLOGGERS][8];
// Declare the output files
char newfile[];
char newfile_hum[MAXLOGGERS][8];
int main()
{
int n = 2;
while (n > MAXLOGGERS)
{
printf("n error, n must be < %d: ", MAXLOGGERS);
scanf("%d", &n);
}
// Initialize the input and output file names
strncpy(inputfile_hum[1], "Ahum.csv", 8);
strncpy(inputfile_hum[2], "Bhum.csv", 8);
strncpy(newfile_hum[1], "Ahum.txt", 8);
strncpy(newfile_hum[2], "Bhum.txt", 8);
for (int i = 1; i < n + 1; i++)
{
strncpy(inputfile, inputfile_hum[i], 8);
FILE* file1 = fopen(inputfile, "r");
// Safety check
while (file1 == NULL)
{
printf("\nError: %s == NULL\n", inputfile);
printf("\nPress enter to exit:");
getchar();
return 0;
}
strncpy(newfile, newfile_hum[i], 8);
FILE* file2 = fopen(newfile, "w");
// Safety check
if (file2 == NULL)
{
printf("Error: file2 == NULL\n");
getchar();
return 0;
}
for (int c = fgetc(file1); c != EOF; c = fgetc(file1))
{
fprintf(file2, "%c", c);
}
fclose(file1);
fclose(file2);
}
// system("Ahum.txt");
// system("Bhum.txt");
}
This code produces two files but instead of the names:
Ahum.txt
Bhum.txt
the files are named:
Ahum.txtv
Bhum.txtv
The reason I am using strncpy in the for loop is because n will actually be inputted by the user later.
I see at least three problems here.
The first problem is that your character array is too small for your strings.
"ahum.txt", etc. will need to take nine characters. Eight for the actual text plus one more for the null terminating character.
The second problem is that you have declared the character arrays "newfile" and "inputfile" as empty arrays. These also need to be a number able to contain the strings (at least 9).
You're lucky to have not had a crash from overwriting memory out the program space.
The third and final problem is your use of strcpy().
strncpy(dest, src, n) will copy n characters from src to dest, but it won't copy final null terminator character if n is equal or less than size of the src string.
From strncpy() manpage: https://linux.die.net/man/3/strncpy
The strncpy() function ... at most n bytes of src are copied.
Warning: If there is no null byte among the first n bytes of src,
the string placed in dest will not be null-terminated.
Normally what you would want to do is have "n" be the size of the destination buffer minus 1 to allow for the null character.
For example:
strncpy(dest, src, sizeof(dest) - 1); // assuming dest is char array
There are a couple of problems with your code.
inputfile_hum, newfile_hum, need to be to be one char bigger for the trailing '\0' on strings.
char inputfile_hum[MAXLOGGERS][9];
...
char newfile_hum[MAXLOGGERS][9];
strncpy expects the first argument to be a char * region big enough to hold the expected results, so inputfile[] and outputfile[] need to be declared:
char inputfile[9];
char outputfile[9];

scanf hangs when copy and paste many line of inputs at a time

This may be a simple question, but I'm new to C, and yet couldn't find any answer. My program is simple, it takes 21 lines of string input in a for loop, and print them after that. The number could be less or greater.
int t = 21;
char *lines[t];
for (i = 0; i < t; i++) {
lines[i] = malloc(100);
scanf("%s", lines[i]);
}
for (int i = 0; i < t; i++) {
printf("%s\n", lines[i]);
free(lines[i]);
}
...
So when I copy & paste the inputs at a time, my program hangs, no error, no crash. It's fine if there's only 20 lines or below. And if I enter by hand line by line, it works normally regardless of number of inputs.
I'm using XCode 5 in Mac OS X 10.10, but I don't think this is the issue.
Update:
I tried to debug it when the program hangs, it stopped when i == 20 at the line below:
0x7fff9209430a: jae 0x7fff92094314 ; __read_nocancel + 20
The issue may be related to scanf, but it's so confused, why the number 20? May be I'm using it the wrong way, great thanks to any help.
Update:
I have tried to compile the program using the CLI gcc. It works just fine. So, it is the issue of XCode eventually. Somehow it prevents user from pasting multiple inputs.
Use fgets when you want to read a string in C , and see this documentation about that function:
[FGETS Function]
So you should use it like this :
fgets (lines[i],100,stdin);
So it'll get the string from the input of the user and you can have a look on these two posts as well about reading strings in C:
Post1
Post2
I hope that this'll help you with your problem.
Edit :
#include <stdio.h>
void main(){
int t = 21;
int i;
char *lines[t];
for (i = 0; i < t; i++) {
lines[i] = malloc(100);
fgets(lines[i],255,stdin);
}
for (i = 0; i < t; i++) {
printf("String %d : %s\n",i, lines[i]);
free(lines[i]);
}
}
This code gives :
As you can see , I got the 21 strings that I entered (From 0 to 20, that's why it stops when i==20).
I tried with your input ,here's the results :
I wrote the same code and ran. It works.
It might contain more than 99 characters (include line feed) per line...
Or it might contain spaces and tabs.
scanf(3)
When one or more whitespace characters (space, horizontal tab \t, vertical tab \v, form feed \f, carriage return \r, newline or linefeed \n) occur in the format string, input data up to the first non-whitespace character is read, or until no more data remains. If no whitespace characters are found in the input data, the scanning is complete, and the function returns.
To avoid this, try
scanf ("%[^\n]%*c", lines[i]);
The whole code is:
#include <stdio.h>
int main() {
const int T = 5;
char lines[T][100]; // length: 99 (null terminated string)
// if the length per line is fixed, you don't need to use malloc.
printf("input -------\n");
for (int i = 0; i < T; i++) {
scanf ("%[^\n]%*c", lines[i]);
}
printf("result -------\n");
for (int i = 0; i < T; i++) {
printf("%s\n", lines[i]);
}
return 0;
}
If you still continue to face the problem, show us the input data and more details. Best regards.

Type conversion - string of characters to integer

Hello I am writing my program in C, using PSoC tools to program my Cypress development kit. I am facing an issue regarding type conversion of a string of characters collected in my circular buffer (buffer) to a local variable "input_R", ultimately to a global variable st_input_R. The event in my FSM calling this action function is given below:
void st_state_5_event_0(void) //S6 OR S4
{
char buffer[ST_NODE_LIMIT] = {0};
st_copy_buffer(buffer);
uint32 input_R = {0};
mi_utoa(input_R, buffer);
if ((input_R >= 19000) && (input_R <= 26000))
{
st_input_R = input_R;
_st_data.state = ST_STATE_6;
}
else
{
_st_data.status = ST_STATE_4;
}
UART_1_Stop();
st_stop();
st_empty_buffer();
}
ST_NODE_LIMIT = 64
st_copy_buffer copies the the numbers I type in using hyper terminal to the circular buffer named "buffer".
input_R is the 32 bit integer I want the buffer content to be converted to.
mi_utoa is the function I am using for converting the contents in the buffer to input_R and is detailed below:
uint8 mi_utoa(uint32 number, char *string)
{
uint8 result = MI_BAD_ARGUMENT;
if (string != NULL)
{
uint8 c = 0;
uint8 i = 0;
uint8 j = 0;
do
{
string[i++] = number % 10 + '0';
} while ((number /=10) > 0);
string[i] = '\0';
for (i = 0, j = strlen(string) - 1 ; i < j ; i++, j--)
{
c = string[i];
string[i] = string[j];
string[j] = c;
}
result = MI_SUCCESS;
}
return result;
}
The problem is, suppose if I enter 21500(+\r), the mi_utoa function converts the first digit to 0 the second digit to \000 while the other digits including the carriage return "\r" remains unaltered. As a result the input_R is NOT = 21500. Its happening for any string of digits I input. So the condition "if ((input_R >= 19000) && (input_R <= 26000))" is never satisfied. Hence the FSM returns to state 4 all the time and I am going in circles.
Can you please advice where the bug is in the mi_utoa function? Let me know if you want to know any other details.
Your function st_state_5_event_0() sets the value input_R to zero. Then you call mi_utoa(), which converts the value input_R to an ascii string, "0".
void st_state_5_event_0(void) //S6 OR S4
{
char buffer[ST_NODE_LIMIT] = {0};
//what is the value of buffer after this statement?
st_copy_buffer(buffer);
//the value of input_R after the next statement is =0
uint32 input_R = {0};
//conversion of input_R to string will give ="0"
mi_utoa(input_R, buffer);
if ((input_R >= 19000) && (input_R <= 26000))
{
st_input_R = input_R;
_st_data.state = ST_STATE_6;
}
//...
}
You probably want a function which converts your ascii buffer to a number.
uint8
mi_atou(uint32* number, char *string)
{
uint8 result = MI_BAD_ARGUMENT;
if (!string) return result;
if (!number) return result;
uint8 ndx = 0;
uint32 accum=0;
for( ndx=0; string[ndx]; ++ndx )
{
if( (string[ndx] >= '0') && (string[ndx] <= '9') )
{
accum = accum*10 + (string[ndx]-'0');
//printf("[%d] %s -> %d\n",ndx,string,accum);
}
else break;
}
//printf("[%d] %s -> %d\n",ndx,string,accum);
*number = accum;
result = MI_SUCCESS;
return result;
}
Which you would call by providing the address of the number to store the result,
mi_atou(&input_R, buffer);

How to search a specific word in lex given a input file?

I am very new to lex. I am trying to develop a parser to search a count of specific word in an given input file...
My code is
%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int lnum = 1, fresult = 0, cc=0, wc=0, lc=0, bc=0, sc=0, nc=0, tc=0, result;
char temp[20], str[20], fname[20];
FILE *fp;
#undef yywrap
%}
digit[0-9]+
word [a-zA-Z]+
eol [\n]
blank [ ]
tab [\t]
result [word]
%%
{result} {
if((strstr(temp, str)) != 0)
{
printf(" A match found on line: %d\n", lnum);
fresult++;
wc++;
cc+=yyleng;
}
lnum++;
if(fresult == 0)
{
printf(" Match not found\n");
}
}
{digit} {nc++;}
{word} {wc++; cc+=yyleng;}
{tab} {tc++;}
{blank} {bc++;}
{eol} {lc++;}
. sc++;
%%
int main(int argc, char *argv[])
{
strcpy(fname,argv[1]);
strcpy(str,argv[2]);
fp=fopen(fname,"r+");
yyin=fp;
yylex();
printf(" Total count of the word is :%d\n", fresult);
printf(" Character Count = %d\n", cc);
printf(" Number Count = %d\n", nc);
printf(" Word Count = %d\n", wc);
printf(" Line Count = %d\n", lc);
printf(" Special Character Count = %d\n", sc);
printf(" Blank Count = %d\n", bc);
printf(" Tab Count = %d\n", tc);
return(0);
}
int yywrap()
{
return -1;
}
The word count and others are working perfectly.... But the word search is taking the input but not given the specific count...... How can I improve the code?
Should I need to add anything?
Thanks in Advance...... :)
I have made some changes to your code to help you in the right direction. First, I created a variable to keep track of whether a match is found or not.
Secondly, I am not using strstr() anymore and instead I am using strcmp() because you want to match a word to a word not a word within a sentence and we do not need a pointer returned. strcmp() is nice because we just get an integer.
I see what you were trying to do with result [word] however, as you found out, this will not work. This section of the Flex file is known as the rules section. Here you use the regular expressions that you defined in the above section (definitions) to tell Flex what to do when a rule is matched.
As you can see, I have deleted all occurrences of result[word] - as this will not work. In the rules section, I also deleted the result definition because we no longer have a rule to match it. However, I keep the code for the result definitions and simply apply it to the word definition.
The last major change is adding the <<EOF>> rule which is a special rule that tells Flex what to do when it has encountered the end of the file. In our case, if the match variable is not 1, then we have not found a match and we would like to print this to the screen. We also need to call yyterminate() (definition at the bottom of the page) to stop the lexical analyzer.
Below is the updated code. I hope that helps!
%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int lnum = 1, fresult = 0, cc=0, wc=0, lc=0, bc=0, sc=0, nc=0, tc=0, result;
char temp[20], str[20], fname[20];
FILE *fp;
int match = 0;//For keeping track of matches
#undef yywrap
%}
/*Rules*/
digit [0-9]+
word [a-zA-Z]+
eol [\n]
blank [ ]
tab [\t]
/*Definitions*/
%%
{digit} {
nc++;
}
{tab} {
tc++;
}
{blank} {
bc++;
}
{eol} {
lc++;
}
{word} {
if((strcmp(yytext, str)) == 0)//We found a match
{
printf("\n A match found on line: %d\n", lnum);
fresult++;
wc++;
cc+=yyleng;
match = 1;//We have a match
}
else //We found a word, but it was not a match
{
wc++;
}
}
. {
sc++;
}
<<EOF>> {
if(!match)
{
printf(" Match not found\n");
}
yyterminate();
}
%%
int main(int argc, char *argv[])
{
strcpy(fname,argv[1]);
strcpy(str,argv[2]);
fp = fopen(fname,"r+");
yyin = fp;
yylex();
printf("\n\n Total count of the word is :%d\n", fresult);
printf(" Character Count = %d\n", cc);
printf(" Number Count = %d\n", nc);
printf(" Word Count = %d\n", wc);
printf(" Line Count = %d\n", lc);
printf(" Special Character Count = %d\n", sc);
printf(" Blank Count = %d\n", bc);
printf(" Tab Count = %d\n", tc);
fclose(fp);
return(0);
}
int yywrap()
{
return 1;
}
{result} {
if((strstr(temp, str)) != 0)
result [word]
Result is a regex for the characters 'w', 'o', 'r', 'd', which is not what you want. You probably want to match on {word}. In addition, temp will always be null - I think you want to use yytext instead.