Can someone please tell me why this code will not work? It does compile. When I type decrypt as the argv[1] argument in the command line, it still gives me the else output. i.e. argv[1] is not satisfied even though it should be. This is a work in progress so ignore the other code
if ((argv[1] == "decrypt"))
{
printf("Decrypting...\n");
c = getc(fp1);
if (c != EOF)
{
fread(inputbuffer, sizeof(char), 50 , fp1);
printf("%s", inputbuffer);
/*while(inputbuffer[i]!=EOF)
{
fputc((inputbuffer[i] / 2) - 5, fp2);
}*/
}
}
else {printf("argv not working");}
You need to use strcmp() to compare strings:
if ((strcmp(argv[1], "decrypt") == 0)
More detail:
What you are comparing are the two memory addresses for the different strings, which are stored in different locations. Doing so essentially looks like this:
if(0x00403064 == 0x002D316A) // Two memory locations
{
printf("Yes, equal");
}
Related
So I'm scanning strings from a file and comparing them with the string from a stack. If i scan all the string from the file and don't find the one from the stack i want to rewind the file, pop the string from the stack and continue unless the stack is empty.
char buffer[ENOUGH];
while(fscanf(stream, "%s", buffer) != EOF)
{
if(strcmp(buffer, tos->string) == 0)
{
pop(&tos);
//do something with the string
}
// here i would need something to stop the EOF
}
I have a file like this:
02.01.2021 8:45 8:57 9:45
03.01.2021 15:40 16:30
05.01.2021 07:30 08:30
And stack contains:
01.01.2021 <- TOS
02.01.2021
03.01.2021
04.01.2021
So i need to find 01.01.2021 in file and if not there remove it from stack.
To avoid reading the stream till the end of file, just break from the loop. Also note that you should compare the return value of fscanf() to 1 to detect all cases of failure. fscanf() will not return 0 for the %s or %c conversions, but would do so for other specifiers in case of a match failure that does not happen at end of file. Also pass a maximum number of characters to avoid undefined behavior on long input strings.
char buffer[100];
while (fscanf(stream, "%99s", buffer) == 1) {
if (strcmp(buffer, tos->string) == 0) {
pop(&tos);
//do something with the string
break; // break from the loop.
}
}
rewind(stream);
Probably something like this:
while (1)
{
if (fscanf(stream, "%s", buffer) != EOF)
{
if (strcmp(buffer, tos->string) == 0)
{
if (stack is empty)
break;
pop(&tos);
//do something with the string
}
}
else
{
fseek(stream, 0, SEEK_SET);
}
}
This is untested code, but you should get the idea.
But there is something flawed in your algorithm anyway: what happens if strcmp(buffer, tos->string) is never true?
You can use a method,
#include <stdio.h>
void compare(){
char buffer[ENOUGH];
while(fscanf(stream, "%s", buffer) != EOF){
if(strcmp(buffer, tos->string) == 0){
//do something
}
}
}
int main(void) {
while(!stactIsEmpty()){
pop();
compare();
}
return 0;
}
This code is not tested. I hope you'll get the idea.
I am building a program that is suppose to look for words from a file that has 2 vowels in a row and ends with either ly or ing. Im currently having some issues with how i am suppose to deal with reading words from the file. My current code looks a little like this
fgets(string, BUFF_SIZE, file);
char *ptr = strtok(string, delim);
reti = regcomp(®ex, "[aoueiyAOUEIY]+[aoueiyAOUEIY].{0,}(ly|ing|LY|ING)$", REG_EXTENDED);
if (reti){
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
/* Execute regular expression */
reti = regexec(®ex, ptr , 0, NULL, 0);
if (!reti) {
puts("Match");
printf(" %s\n", string);
}
else if (reti == REG_NOMATCH) {
puts("No match");
printf(" %s\n", string);
}
else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
Im aware that i need some sort of loop so that i can check more then one word,i wanted to try how strtok would work but realised that i stil face the same problem. If i for example have the line fairly standing. jumping? hoping! there is just to many "chars" that a word can end on, how to i make my delim understand that it's at an end of a word. Im thinking of doing a second regex that only has letter in it and compare until i get a reg no match. But the issue with that is that the buffer will get full very quickly.
For a task like this it's important to define "what is a word".
For instance consider "bad!idea this!is" is that the 4 words "bad", "idea" "this" "is" or is it the 4 words "bad!", "idea" "this!" "is" or is it just the two words "bad!idea" "this!is".
And what if the input is "bad3idea this9is" ?
Sometimes the standard functions (e.g. strtok, fscanf) will fit your needs and in such cases you should use them.
In case the standard functions do not fit, you can use fgetc to implement something that fit your needs.
The example below will consider anything that is not a letter (i.e. not a-z or A-Z) as word delimiters.
int end_of_file = 0;
while(!end_of_file)
{
int index = 0;
int c = fgetc(file);
if (c == EOF) break; // Done with the file
while (isalpha(c))
{
string[index] = c;
++index;
if (index == BUFF_SIZE)
{
// oh dear, the buffer is too small
//
// Just end the program...
exit(1);
}
c = fgetc(file);
if (c == EOF)
{
end_of_file = 1;
break;
}
}
string[index] = '\0';
if (index >= 4) // We need at least 4 chars for a match
{
// do the regex stuff
}
}
I am in the process of writing an encryption program but have come to a halt because of the error: 'Segmentation Fault(Core Dumped)'. The below program is suppose to print from two input files:
The first input file: should be read in and then change the upper case characters to lower case characters and lower case characters to upper case characters.
The second input file: should be read in and just print the number of times the user desired character appears in the file. In this case the user desired character I want is the letter 'a'.
Let's say for example the first input file(input.txt) contains:
Hello My Name is Joe
This should print as: hELLO mY nAME IS jOE
Let's say for example the second input file(keys.txt) contains:
A
M
This should just print the character: A
NOTE This doesn't necessarily encrypt the input file yet however, i'm trying to get familiar with using more than one input file at once. I can use all the help I can get! THANK YOU!
ALSO, when compiling, the code should look like this:
gcc myProgram.c
./a.out e input.txt keys.txt
(The above 'e' just stands for encryption.)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int args, char *argc[]){
int i,c,x,len,len2;
char str[1024];
char str2[500];
FILE *finp;
FILE *keyFile;
/* ****** CODE TO ENCRYPT STARTS HERE ****** */
if((argc[1]="e")&&((finp = fopen(argc[2],"r"))==NULL)
&&((keyFile=fopen(argc[3],"r"))==NULL)){
printf("Could Not Open file %s\n", argc[2]);
exit(1);
}//End First IF statement
/* *** START CODE TO GRAB FROM 1st INPUT FILE: input.txt *** */
/*Grab strings from first input file and change lower case to upper case and
upper to lower case*/
while(fgets(str,1024,finp)!=NULL){
len = strlen(str);
for(i>0;i<len;++i){
if(((str[i]>=64)&&(str[i]<=90))||((str[i]>=97&&(str[i]<=122))))
str[i]^=32;}}
/* *** END OF CODE FOR 1st INPUT FILE **** */
/* *** START CODE TO GRAB FROM 2nd INPUT FILE: keys.txt **** */
/*Grab character from second input file and print the character*/
while(fgets(str2,500,keyFile)!=NULL){
len2 = strlen(str2);
for(x>0;x<len2;++x){
if(str2[x]=='A'){
putchar(str2[x]);
}}
/* ***** END CODE FOR 2nd INPUT FILE*** */
}
printf("%s\n",str);
fclose(finp);
return 0;}
I think the main problem in your code is that you have not initialized i and x before using them.
Replace the line
for(i>0;i<len;++i){
with
for(i=0;i<len;++i){
// ^^^ i = 0; not i > 0;
and replace the line
for(x>0;x<len2;++x){
with
for(x=0;x<len2;++x){
// ^^^ x = 0; not x > 0;
You can clean up the code at the start of the function. The logic used in
if((argc[1]="e")&&((finp = fopen(argc[2],"r"))==NULL)
&&((keyFile=fopen(argc[3],"r"))==NULL)){
printf("Could Not Open file %s\n", argc[2]);
exit(1);
}//End First IF statement
is wrong on many accounts. Replace that with more readable code:
if ( strcmp(argv[1], "e") == 0 )
{
if ( (finp = fopen(argc[2],"r")) == NULL )
{
printf("Could Not Open file %s\n", argc[2]);
exit(1);
}
if ( (keyFile = fopen(argc[3],"r")) == NULL )
{
printf("Could Not Open file %s\n", argc[3]);
exit(1);
}
}
else
{
// Decide what you want to do when the first argument is not "e".
}
in your code
(argc[1]="e")
should be
!strcmp(argv[1], "e")
Same kind of mistake for argc[2] and argc[3].
Remember, argc is of type int (not array). argv[] is of type char *.
That said, you should always check for the argc value against n befire making use of argv[n-1].
Then, please keep in mind, the second operand of && is evaluated only if the first operand yields a TRUE value. You shoule check the logic you're using in
if((argc[1]="e")&&((finp = fopen(argc[2],"r"))==NULL)
&&((keyFile=fopen(argc[3],"r"))==NULL))
I don't think it serves the purpose you want it to serve.
Also, as pointed out by Mr. #iharob, you never seem to initialize the counter variables used in either of your for loops. This will lead to undefined behavior.
You have many many errors
The first if statement, is completely wrong
The argc[1] = "e", is wrong from many points of view, first you cant compre strings with the == operator, but you didn't use the comparison operator, it's the assignment operator and you can't assign to arrays, so it's twofold wrong.
You used the && operator to check if both files where NULL at the same time, which would be false if only one of them is, making the code that follows invoke undefined behavior, possibly causing the SEGMENTATION FAULT.
You never check if the program was invoked with the correct number of arguments, but you still access the argc array, which by the way is normally argv, argc is used for the number of parameters i.e. where you used args, but that doesn't actually matter.
Your for loops are also wrong
for (i > 0 ... )
you never initialize the i, also a little bit of knowledge of how strings work in c, would make a c programmer to write the following loop to traverse the string
for (i = 0 ; ((str[i] != '\n') && (str[i] != '\0')) ; ++i)
since fgets() will read the trailing '\n' inserted by pressing the Return/Enter key and thus flushing standard input, you need to check against str[i] == '\n' but if you are paranoid you should also check for '\0' I am paranoid and I do check although that is ineficient, I prefer to do it instead of seeing unexpected things later.
Here is a sample of your program without the mistakes, I don't know if it does what you want but it's the same program just with errors that could lead to SEGMENTATION FAULT corrected
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char *argb[])
{
int i;
char str[1024];
char str2[500];
FILE *inputFile;
FILE *keyFile;
if (argc < 3) /* insufficient number of parameters provided */
return -1;
if (argb[1][0] == 'e')
return 0;
inputFile = fopen(argb[2], "r");
if (inputFile == NULL)
{
printf("Could Not Open file %s\n", argb[2]);
return -1;
}
keyFile = fopen(argb[3], "r");
if (keyFile == NULL)
{
printf("Could Not Open file %s\n", argb[2]);
fclose(inputFile);
return -1;
}
while (fgets(str, sizeof(str), inputFile) != NULL)
{
for (i = 0 ; ((str[i] != '\n') && (str[i] != '\0')) ; ++i)
{
if (((str[i] >= 64) && (str[i] <= 90)) || ((str[i] >= 97) && (str[i]<=122)))
str[i] ^= 32;
}
}
while (fgets(str2, sizeof(str2), keyFile) != NULL)
{
for (i = 0 ; ((str2[i] != '\n') && (str2[i] != '\0')) ; ++i)
{
if (str2[i] == 'A')
putchar(str2[i]);
}
}
printf("%s\n", str);
fclose(inputFile);
return 0;
}
I'm having trouble using strcmp in C.
I'm trying to compare a program's arguments using strcmp but even though the strings are the same it doesn't work. Here is the portion of code.
while(strcmp(argv[i], "-e") != 0)
So for i = 11 if I print the value of argv[i] I get
printf("String %s i %d", argv[i],i);
>> String -e i 11
But the while keeps on going. Any ideas why this is happening?
Code:
while(strcmp(argv[i], "-e") != 0 || i != argc)
{
printf("String %s i %d", argv[i],i);
if(!isdigit((unsigned char)*argv[i]) && strcmp(argv[i], "-t") != 0)
{
archivo = fopen(argv[i] , "r");
TOT_IMG = TOT_IMG + 1;
for(t=0;t<NUM_FUNC_TRAZO;t++)
{
for(d=0;d<NUM_FUNC_DIAMETRICA;d++)
{
for(c=0;c<NUM_FUNC_CIRCO;c++)
{
if (fscanf(archivo, "%s",el) != EOF)
{
par->vector_circo[t][d][c] = strtod(el,NULL);
par->clase = clase;
}
else
{
break;
}
}
}
}
par_temp = par;
par->siguiente = (parametros_lista) malloc(sizeof(parametros_elem));
par = par->siguiente;
par->anterior = par_temp;
}
else
{
if(strcmp(argv[i], "-t") != 0)
{
clase = atoi(argv[i]);
CLASES = CLASES + 1;
}
}
i = i + 1;
}
Let's look at this:
while(strcmp(argv[i], "-e") != 0 || i != argc)
OK, so let's assume strcmp correctly returns 0 when argv[i] is "e". We'll assume this because it's exceedingly unlikely that there's a bug in your library implementation of strcmp.
What happens if strcmp returns 0? Well, things don't just stop, your code checks whether i != argc is true. Is it? My psychic debugging skills tell me that you should look into that second part of the while.
You may also want to note that it's possible that your code could, potentially, access argv[argc], which is NULL. You may get lucky if strcmp is lenient when the input is NULL, but it's a bug that you should fix.
I'd rather recommend you to use getopt (3). This is widely used approach to parameters parsing conforming with POSIX.
Also there was another question related to achieving getopt.h interface on windows: getopt.h: Compiling UNIX C-Code in Windows. What's important it is answered (Xgetopt) so portability should be not a case.
EDIT:
complete code with main is here http://codepad.org/79aLzj2H
and once again this is were the weird behavious is happening
for (i = 0; i<tab_size; i++)
{
//CORRECT OUTPUT
printf("%s\n", tableau[i].capitale);
printf("%s\n", tableau[i].pays);
printf("%s\n", tableau[i].commentaire);
//WRONG OUTPUT
//printf("%s --- %s --- %s |\n", tableau[i].capitale, tableau[i].pays, tableau[i].commentaire);
}
I have an array of the following strcuture
struct T_info
{
char capitale[255];
char pays[255];
char commentaire[255];
};
struct T_info *tableau;
This is how the array is populated
int advance(FILE *f)
{
char c;
c = getc(f);
if(c == '\n')
return 0;
while(c != EOF && (c == ' ' || c == '\t'))
{
c = getc(f);
}
return fseek(f, -1, SEEK_CUR);
}
int get_word(FILE *f, char * buffer)
{
char c;
int count = 0;
int space = 0;
while((c = getc(f)) != EOF)
{
if (c == '\n')
{
buffer[count] = '\0';
return -2;
}
if ((c == ' ' || c == '\t') && space < 1)
{
buffer[count] = c;
count ++;
space++;
}
else
{
if (c != ' ' && c != '\t')
{
buffer[count] = c;
count ++;
space = 0;
}
else /* more than one space*/
{
advance(f);
break;
}
}
}
buffer[count] = '\0';
if(c == EOF)
return -1;
return count;
}
void fill_table(FILE *f,struct T_info *tab)
{
int line = 0, column = 0;
fseek(f, 0, SEEK_SET);
char buffer[MAX_LINE];
char c;
int res;
int i = 0;
while((res = get_word(f, buffer)) != -999)
{
switch(column)
{
case 0:
strcpy(tab[line].capitale, buffer);
column++;
break;
case 1:
strcpy(tab[line].pays, buffer);
column++;
break;
default:
strcpy(tab[line].commentaire, buffer);
column++;
break;
}
/*if I printf each one alone here, everything works ok*/
//last word in line
if (res == -2)
{
if (column == 2)
{
strcpy(tab[line].commentaire, " ");
}
//wrong output here
printf("%s -- %s -- %s\n", tab[line].capitale, tab[line].pays, tab[line].commentaire);
column = 0;
line++;
continue;
}
column = column % 3;
if (column == 0)
{
line++;
}
/*EOF reached*/
if(res == -1)
return;
}
return ;
}
Edit :
trying this
printf("%s -- ", tab[line].capitale);
printf("%s --", tab[line].pays);
printf("%s --\n", tab[line].commentaire);
gives me as result
-- --abi -- Emirats arabes unis
I expect to get
Abu Dhabi -- Emirats arabes unis --
Am I missing something?
Does printf have side effects?
Well, it prints to the screen. That's a side effect. Other than that: no.
is printf changing its parameters
No
I get wrong resutts [...] what is going on?
If by wrong results you mean that the output does not appear when it should, this is probably just a line buffering issue (your second version does not print newline which may cause the output to not be flushed).
It's highly unlikely that printf is your problem. What is far, far more likely is that you're corrupting memory and your strange results from printf are just a symptom.
There are several places I see in your code which might result in reading or writing past the end of an array. It's hard to say which of them might be causing you problems without seeing your input, but here are a few that I noticed:
get_lines_count won't count the last line if it doesn't end in a newline, but your other methods will process that line
advance will skip over a newline if it is preceded by spaces, which will cause your column-based processing to get off, and could result in some of your strings being uninitialized
get_word doesn't do any bounds checks on buffer
There may be others, those were just the ones that popped out at me.
I tested your code, adding the missing parts (MAX_LINE constant, main function and a sample datafile with three columns separated by 2+ whitespace), and the code works as expected.
Perhaps the code you posted is still not complete (fill_table() looks for a -999 magic number from get_word(), but get_word() never returns that), your main function is missing, so we don't know if you are properly allocating memory, etc.
Unrelated but important: it is not recommended (and also not portable) to do relative movements with fseek in text files. You probably want to use ungetc instead in this case. If you really want to move the file pointer while reading a text stream, you should use fgetpos and fsetpos.
Your approach for getting help is very wrong. You assumed that printf had side effects without even understanding your code. The problem is clearly not in printf, but you held information unnecessarily. Your code is not complete. You should create a reduced testcase that compiles and displays your problem clearly, and include it in full in your question. Don't blame random library functions if you don't understand what is really wrong with your program. The problem can be anywhere.
From your comments, i am assuming if you use these printf statements,
printf("%s\n", tableau[i].capitale);
printf("%s", tableau[i].pays);
printf("%s\n", tableau[i].commentaire);
then everything works fine...
So try replacing your single printf statement with this. (Line no. 173 in http://codepad.org/79aLzj2H)
printf("%s\n %s %s /n", tableau[i].capitale, tableau[i].pays, tableau[i].commentaire);