When I read from file I want to check the word do not contains the number, for example, 2sum or 23b2 but is OK if the file read the mathematical operation like
sum = x + 5
I try to put inside the if statement [a-zA-Z]* put it does not work.
This part of my code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int charClass;
char lexeme [100];
void addChar();
void getChar();
void getNonBlank();
int lex();
int main() {
if ((in_fp = fopen("/Users/Desktop/ff.txt", "r")) == NULL)
printf("ERROR - cannot open front.in \n");
else {
getChar();
do {
if(strcmp(lexeme, "[a-zA-Z]*") == 0){
printf("error");
break;
}
lex();
} while (nextToken != EOF);
}
}
Regarding:
if(strcmp(lexeme, "[a-zA-Z]*") == 0){
This is comparing the char array [a-zA-Z]* to the array pointed at by lexeme
There are two ways to approach this problem.
First, use an regular expression, which requires several complexities that will just confuse you (or me)
Second, iterate over the expression pointed to by: lexeme as in:
for( size_t i=0; lexeme[i]; i++ )
{
if( isalpha( lexeme[i] )
{
....
}
}
The functions in ctype.h work on indivdual int values and when referencing: lexeme[i] that single character gets prompted to an 'int'
Related
is there a way to have optional input variables in scanf ?
I have a program that scans input until EOF. That input can look like this:
+ 10 20 30
- 10 20 30
? 10
When I type (or read from a file) + or - it is always followed by three numbers but when I type in ? it is only followed by one number (always).
My current code looks like this:
#include <stdio.h>
#include <stdlib.h>
int main(){
char action;
int dc1,dc2,cable;
while(scanf(" %c %d %d %d",&action,&dc1,&dc2,&cable)!=EOF){
if((dc1==dc2)||(cable<1)||(dc1>999)||(dc2>999)||(dc1<0)||(dc2<0)){
printf("Wrong input.\n");
return 0;
}
else{
if(action=='+'){
/*code*/
}
else if(action=='-'){
/*code*/
}
else if(action=='?'){
/*code*/
}
else{
printf("Wrong input.\n");
return 0;
}
}
}
return 0;
}
Right now it requires me to type in three numbers all the time, even if I want to type in the "?" action.
Is there a way to make some of the variables in scanf optional so the input "? 10" would also be valid.
PS.
I have stripped the code so it is not too long. I hope I have included everything that is necessary.
I would also appreciate if I didn't have to rework the code too much because it is basically done, everything works like it needs to. This is the only thing that is stopping me from turning in my code.
PPS. This is for a homework.
As mentioned in comment this can be easily checked with sscanf() and fgets.
We are using the fgets to read a line and then pass it to the parser function. That function tries to parse the line. sscanf returns the successful number of parameters passed. Based on that count we are deciding which input it is.
This code is just a starting point for how to start. It avoids the lots of error checking and concentrates on the technique as discussed above by Jonathan Leffler.
Code example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 256
void add (int b,int c,int d){
printf("%d+%d+%d=%d\n",b,c,d,b+c+d);
}
void sub (int b,int c,int d){
printf("%d-%d-%d=%d\n",b,c,d,b-c-d);
}
void query (int a){
printf("?%d\n",a);
}
void parseAndProcess(const char *buf){
char a;
int b, c, d;
size_t ct;
ct = sscanf(buf,"%c%d%d%d",&a,&b,&c,&d);
if( ct <= 1){
//error
}
else if( ct==2 ) {
if( a == '?'){
query(b);
}
else{
//error
}
}
else if( ct == 3){
// error
}
else if( ct == 4){
if( a == '+') add(b,c,d);
else if( a == '-') sub(b,c,d);
else{
//error
}
}
else{
// error
}
}
int main(void){
char buf[BUFFSIZE];
while(fgets(buf,BUFFSIZE,stdin)){
parseAndProcess(buf);
}
return EXIT_SUCCESS;
}
Here add,sub methods are to be implemented for actual code. A demo implementation is shown here above. For example here in add,sub no overflow checking is there.
I want to make a program that has a key to open. But when i comparing the key and the input, it always says "Wrong":
#include <stdio.h>
int main(){
char key[5]="april",ckey[5];
printf("Enter the key: ");
scanf("%s",ckey);
if(ckey==key){
printf("Correct.");
}
else{
printf("Wrong.");
}
return 0;
}
Is it possible to solve the problem without using other libraries?
You have to leave space before "%s" inside the scanf statement,so that the '\n character is not stored in ckey to ensure success of comparison.note: ckey must have size 6 or more.
#include <stdio.h>
#include <string.h>
int main(){
char key[] = "april",ckey[6];
printf("Enter the key: ");
scanf(" %5s",ckey);
if(!strcmp(ckey, key)){
printf("Correct.");
}
else{
printf("Wrong.");
}
return 0;
}
you have to check character by character.
try this code :
int main(){
int i = 0 ; int j = 1;
char key[6]="april",ckey[6];
printf("Enter the key: ");
scanf("%s",ckey);
for(i = 0; i < 6; i++){
if(ckey[i] != key[i])
j=0;
}
if(j == 1)
printf(%s,"Correct.");
else
printf(%s,"Wrong.");
return 0;
}
You make several mistakes in array sizing for your keys. Remember, a C string is always terminated by a nul character and you must account for this when you size your arrays to accept such strings.
scanf is unsafe, don't use it. Use fgets instead. A safe use of fgets is:
fgets (buffer, sizeof(buffer), stdin);
The answer to your question is no, it would be better to use strcmp if you want to lexically compare strings in C and that would involve including the header. But even so, this is not adding any other "libraries" since fgets and strcmp are in the same standard C library.
If you must not add any other headers (which makes no sense if this is part of a larger project but makes perfect sense if this is a homework problem) then you can write your own strcmp (we'll call it compare here) and call it from main.
#include <stdio.h>
int compare (const char* src, const char* dst)
{
int ret = 0;
while( ! (ret = *src - *dst) && *dst){
++src, ++dst;
}
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
int main(void){
char key[6]="april",ckey[6];
printf("Enter the key: ");
fgets(ckey, sizeof ckey, stdin);
if(!compare(key,ckey)) {
printf("Correct.");
}
else {
printf("Wrong.");
}
return 0;
}
A better use of your time would be to write it using the functions available to you in the standard C library:
#include <stdio.h>
#include <string.h>
int main(void){
char key[6]="april",ckey[6];
printf("Enter the key: ");
fgets(ckey, sizeof ckey, stdin);
if(!strcmp(key,ckey)) {
printf("Correct.");
}
else {
printf("Wrong.");
}
return 0;
}
But even this solution has a flaw. It will accept "aprilaaaa" or any string beginning with "april" as a valid ckey. Can you explain why? How would you fix this?
In the condition of the if statement
if(ckey==key){
there are compared two addresses of the memory areas occupied by the arrays.
So you will always get false because the arrays occupy different memory areas.
If you may not use other standard functions as for example strncmp or memcmp declared in header <string.h> then you can write the following way
#include <stdio.h>
int main( void ){
char key[5]="april",ckey[6];
printf("Enter the key: ");
scanf("%5s",ckey);
size_t i = 0;
while ( i < sizeof( key ) && key[i] == ckey[i] ) ++i;
if( i == sizeof( key ) ){
printf("Correct.");
}
else{
printf("Wrong.");
}
return 0;
}
Instead of scanf it would be better to use fgets. In this case the size of the array ckey must be increased.
This declaration
char key[5]="april";
is totally valid in C though is not valid in C++.:)
Let's say I've got the file
5f2
3f6
2f1
And the code:(The printf should print the second numbers (i.e 2,6, and 1) but it doesn't
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main (int argc, char * argv[])
{
FILE *ptr;
char str[100];
char * token;
int a, b, i;
int arr[4];
if(argc > 1)
{
ptr = fopen(argv[1],"r");
if(ptr == NULL)
{
exit(1);
}
}
else
{
exit(1);
}
//And I'm looking to parse the numbers between the "f" so..
while(fgets(str,100,ptr) != NULL)
{
token = strstr(str,"f");
if(token != NULL)
{
a = atol(str); // first number
b = atol(token+1); // second number
arr[i] = b; // store each b value (3 of em) into this array
}
i++;
printf("Values are %d\n",arr[i]); //should print 2,6 and 1
}
}
I've tried to move the printf outside the loop, but that seems to print an even weirder result, I've seen posts about storing integers from a file into an array before, however since this involves using strstr, I'm not exactly sure the procedure is the same.
int i,j=0;
while(fgets(str,sizeof(str),file) != NULL)
{
size_t n = strlen(str);
if(n>0 && str[n-1] == '\n')
str[n-1] = '\0';
i = str[strlen(str)-1] - '0'; /* Convert the character to int */
printf("%d\n",i);// Or save it to your int array arr[j++] = i;
}
Just move to the last character as shown and print it out as integer.
PS: fgets() comes with a newline character you need to suppress it as shown
You are never initializing i, then you are reading into arr[i] (which just happens to not crash right there), then increment i (to "undefined value + 1"), then print arr[i] -- i.e., you are writing to and reading from uninitialized memory.
Besides, your FILE * is ptr, not file. And you should get into the habit of using strtol() instead of atol(), because the former allows you to properly check for success (and recover from error).
I'm working on enumerations in C and can't find the source of problem in the following example that, the output is always "Sorry!":
#include <stdio.h>
#include <stdlib.h>
typedef enum
{
summer, winter, fall, spring
} season;
void printPhrase (season s);
int main(void)
{
printf("What's your prefered season? ");
char seasonHold[10], seasonHold2[10];
scanf("%s", seasonHold);
for (int n = 0; n < strlen(seasonHold); n++)
{
if (n != '\0')
seasonHold2[n] = seasonHold[n];
}
printPhrase (*seasonHold2);
return 0;
}
void printPhrase (season s)
{
if (s == summer)
printf("It's hot out!\n");
else if (s == fall)
printf("It's getting cooler!\n");
else if (s == winter)
printf("Should be really cold!\n");
else if (s == spring)
printf("It should be lovely outside!\n");
else
printf("Sorry!\n");
}
The problem is whatever input I enter, there's always one output: Sorry!
Thanks.
Also, this can solve the matter:
I could manage it by changing main function into following:
int main(void)
{
printf("What's your prefered season? ");
char seasonHold[10];
scanf("%s", seasonHold);
if (seasonHold[0] == 's')
printPhrase (summer);
else if (seasonHold[0] == 'f')
printPhrase(fall);
else if (seasonHold[1] == 'p')
printPhrase(spring);
else if (seasonHold[0] == 'w')
printPhrase(winter);
return 0;
}
Enums are like constant integers. Here: summer=0, winter=1,...
seansonhold is a char*. By dereferencing it you get a char. This char will then be converted to a 'season' type because char->int does not give compiler errors.
So you basically test here if the first byte of your char array is equal to 0,1,2..
If you are sure seasonHold is null-terminated (it will be here), you can use a pointer and while loop to accomplish what you want:
char *ptr = seasonHold;
n = 0;
while (*ptr++) { /* same as saying while (*ptr++ != '\0') */
seasonHold2[n] = seasonHold[n]; /* could also do: seasonHold2[n] = *ptr; */
n++;
}
seasonHold2[n] = 0; /* null-terminate */
Additionally, if you would like to dynamically allocate seasonHold2, you can simply declare it as a pointer, include string.h and use strdup to copy seasonHold to seasonHold2, e.g.:
#include <string.h>
...
char *seasonHold2;
...
seasonHold2 = strdup (seasonHold);
I am trying to write a program which opens up a text file, reads from the file, changes upper case to lower case, and then counts how many times that word has occurred in the file and prints results into a new text file.
My code so far is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <ctype.h>
#include <string.h>
int main()
{
FILE *fileIN;
FILE *fileOUT;
char str[255];
char c;
int i = 0;
fileIN = fopen ("input.txt", "r");
fileOUT = fopen ("output.txt", "w");
if (fileIN == NULL || fileOUT == NULL)
{
printf("Error opening files\n");
}
else
{
while(! feof(fileIN)) //reading and writing loop
{
fscanf(fileIN, "%s", str); //reading file
i = 0;
c = str[i];
if (isupper(c)) //changing any upper case to lower case
{
c =(tolower(c));
str[i] = putchar(c);
}
printf("%s ", str); //printing output
fprintf(fileOUT, "%s\n", str); //printing into file
}
fclose(fileIN);
fclose(fileOUT);
}
getch();
}
the input.txt file contains the following "The rain in Spain falls mainly in the plane"
Don't ask why.
After the running of the program as is the output would look like:
the
rain
in
spain
falls
mainly
in
the
plane
I have managed to lower case the upper case words. I am now having trouble understanding how I would count the occurrences of each word. eg in the output I would want it to say "the 2" meaning 2 had appeared, this would also mean that i do not want any more "the" to be stored in that file.
I am thinking strcmp and strcpy but unsure how to use those the way i want.
Help would be much appreciated
(Sorry if formatting bad)
You may want to create a hash table with the words as keys and frequencies as values.
Sketch ideas:
recognize words, i.e. alphanumeric string separated by white space, try using strtok()
for each word
search for the word in the hash table based dictionary
if found: increment the frequency
if not found: insert a new entry in the dictionary as (word, 1)
At the end, print the contents of the dictionary, i.e. for all entries, entry.word and entry.frequency
See this question and answer for details: Quick Way to Implement Dictionary in C It is based on Section 6.6 of the bible "The C Programming Language"
UPDATE based on OP's comment:
Hash table is just an efficient table, if you do not want to use it, you can still use vanilla tables. Here are some ideas.
typedef struct WordFreq {
char word[ N ];
int freq;
} WordFreq;
WordFreq wordFreqTable[ T ];
(N is the maximum length of a single word, T is the maximum number of unique words)
For searching and inserting, you can do a linear search in the table for( int i = 0; i != T; ++i ) {
easy sample(need error catch, do free memory, sorting for use qsort, etc...)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define BUFFSIZE 1024
typedef struct _wc {
char *word;
int count;
} WordCounter;
WordCounter *WordCounters = NULL;
int WordCounters_size = 0;
void WordCount(char *word){
static int size = 0;
WordCounter *p=NULL;
int i;
if(NULL==WordCounters){
size = 4;
WordCounters = (WordCounter*)calloc(size, sizeof(WordCounter));
}
for(i=0;i<WordCounters_size;++i){
if(0==strcmp(WordCounters[i].word, word)){
p=WordCounters + i;
break;
}
}
if(p){
p->count += 1;
} else {
if(WordCounters_size == size){
size += 4;
WordCounters = (WordCounter*)realloc(WordCounters, sizeof(WordCounter)*size);
}
if(WordCounters_size < size){
p = WordCounters + WordCounters_size++;
p->word = strdup(word);
p->count = 1;
}
}
}
int main(void){
char buff[BUFFSIZE];
char *wordp;
int i;
while(fgets(buff, BUFFSIZE, stdin)){
strlwr(buff);
for(wordp=buff; NULL!=(wordp=strtok(wordp, ".,!?\"'#$%&()=# \t\n\\;:[]/*-+<>"));wordp=NULL){
if(!isdigit(*wordp) && isalpha(*wordp)){
WordCount(wordp);
}
}
}
for(i=0;i<WordCounters_size;++i){
printf("%s:%d\n", WordCounters[i].word, WordCounters[i].count);
}
return 0;
}
demo
>WordCount.exe
The rain in Spain falls mainly in the plane
^Z
the:2
rain:1
in:2
spain:1
falls:1
mainly:1
plane:1