So i have this big code ( so wont be able to put the entire thing here).
But at a point i have this.
while(ptr1!=NULL)
{
printf("%sab ",ptr1->name);
puts(ptr1->name);
ptr1=ptr1->next;
}
Now my ptr1 point to a an entry of the array of a structure( each entry being a linked list), and the structure was populated from a file.
Now in this loop it prints
FIRSTab FIRST
SECONDab SECOND
THIRD
Now why doesnt my THIRD GETS PRINTED TWICE?
Also if i do
printf(" %s",ptr1->name); // i.e. one space before %s
I get
THIRDD
Putting 2 spaces before %s gives me
THIRDRD
3 spaces gives
THIRDIRD
And so on.
Also if i try to do strcmp(ptr1->name,"THIRD") i wont get the correct comparison for THIRD.
Why??
Here is how i populated my structure.
// G is the structure, fp is passed as argument to function.
//THe file format is like this.
//FIRST SECOND THIRD
//NINE ELEVEN
//FOUR FIVE SIX SEVEN
// and so on.
int i=0,j=0,k=0;
char string[100];
while(!feof(fp))
{
if(fgets(string,100,fp))
{
G[i].index=i;
k=0;j=0;
//\\printf("%d",i);
//puts(string);
node *new=(node*)malloc(sizeof(node));
new->next=NULL;
G[i].ptr=new;
node* pointer;
pointer=G[i].ptr;
while(string[j]!='\n')
{
if(string[j]==' ')
{
pointer->name[k]='\0';
k=0;
node *new=(node*)malloc(sizeof(node));
new->next=NULL;
pointer->next=new;
pointer=pointer->next;
j++;
}
else
{
pointer->name[k++]=string[j];
j++;
}
}
pointer->name[k]='\0';
i++;
}
Your third string probably contains the characters THIRD followed by \r (carriage return). Why it contains this can only be determined by knowing the contents of the file and how your read it.
It is likely that you are either working on a system that uses a single newline character as a line terminator (but the file you are opening comes from a system that uses a carriage return and newline pair) or that the file pointer that you were passed (fp) was opened in binary mode.
If you can't change the file pointer to be opened in text mode then a quick fix might be to change this condition while(string[j]!='\n') to while(string[j]!='\n' && string[j] != '\r'), although you might want a more robust solution that handles multiple whitespace characters.
Related
Hi I'm tyring to use fgets in a C program to see whether or not a name exists in a line in a .csv file. If it does, then it saves it in an array then returns it. Right now, it saves everything line from the .csv file and I'm not sure why.
C file:
void FindRecord(char *filename, char *name, char record[]) {
char *temp = record; //temp save record
FILE *q = fopen(filename, "r"); //check that ths inputed .csv file exists
if (q == NULL ) { //if it doesn't, then print error message and exit
printf("This .csv does not exist");
exit(1); //terminate with error message
}
while(!feof(q)) { //while I'm not at the end of the file
fgets(temp, 1000, q); //Reads a line # a time
for (int i = 0; i < 1000; i++) {
if(temp[i] == *name) {
record[i] = temp[i];
name++;
}
}
printf("%s", record);
}
fclose(q);
}
.csv file:
Kevin, 123-456-7890
Sally, 213-435-6479
Megan, 415-336-8790
Right now whats happening when I run the program is that it returns the 3 lines. I want iso that if *name points to the name "Kevin" and it comes with temp, it'll just return: Kevin, 123-456-7890
Right now whats happening when I run the program is that it returns the 3 lines.
I don't see how that's possible. You have only one array in which to return a result. I could believe that your code prints all three lines, but it will return only the last.
I want iso that if *name points to the name "Kevin" and it comes with temp, it'll just return: Kevin, 123-456-7890
Well, your code has several problems in that regard. Among the most significant are:
Although it performs some character-by-character comparisons, it has no code anywhere to reject lines that fail to match.
It sets temp to point to the same array as record, and then reads each line into that array. This will overwrite that array even in the event that no match is found, and if a match is found on a line other than the last one read then the actual match will be lost.
It modifies the name pointer as it attempts to match, with no mechanism for resetting it in the event of a partial match.
When trying to match the name, it blithely scans past the , delimiter in the input line and, if it comes to them, the string terminators in the name and the input string.
while (!feof(file)) is always wrong.
I am having trouble with a certain aspect of my code in the C programming language. Here is the problem at hand. I have to read in a file that is formatted as so:
q 99
z 8
q 4
Each line starts with either q or z, followed by a tab, followed by a number. I want to store only the numbers that start on line q in a linked list.
I am able to isolate the lines starting with q, but my code separates the value 99 into two separate nodes 9 and 9. I am not sure how to fix this.
Any constructive help would be great, and be kind, I am new to the C language!
// Beginning of code reads the file in, and provides structure and
// function declarations
struct node *start = NULL;
char w;
while((w = fgetc(filep))!= EOF ) //filep is pointer to the file
{
if(w=='z')
break;
else if(isdigit(w))
push(&start, w); //push function creates the nodes
}
// rest of code has function definitions of push and print, creating
// and printing the linked list
You're currently reading character by character. "99" is made up of two characters.
An easy fix for this particular problem would be to use a function designed to parse formatted input like scanf().
Here's an example of how to use it:
while (true) {
char w;
int v;
int count = scanf(" %c %d", &w, &v);
if (count != 2)
break;
if (w == 'q')
push(&start, v);
}
Note that in the format string, I've included a leading space. This will make sure that before we get to the %c, we consume any leading whitespace. This whitespace would include the trailing newline from the previous line.
I've been stuck for a while now. The program i'm writing basically changes the false words with the correct ones from the dictionary. However, when i run the program, it gives me no warnings or errors, but it doesn't display anything. Can you please help me?
#include<stdio.h>
#include<ctype.h>
#include<string.h>
int main(void){
char fname[20],word[2500], dictn[50];
int i,j;
float len1, len2;
FILE *inp, *dict, *outp, *fopen();
fpos_t pos1, pos2;
dict= fopen("dictionary.txt", "r");
printf("Enter the path of the file you want to check:\n");
scanf("%s", fname);
inp= fopen(fname, "r");
for(i=0;(fscanf(inp, "%s", word) != EOF); i++){
for(j=0;fscanf(dict, "%s", dictn) != EOF; j++){
fgetpos(inp, &pos1);
fgetpos(dictn, &pos2);
len1=(float)strlen(word);
len2=(float) strlen(dictn);
if(len1<=(0.6*len2)){
fsetpos(dictn, &pos1);
}
if(strncmp(word, dictn, 1)==0){
fsetpos(dictn, &pos1);
}
if(strcmp(word, dictn)==0){
fsetpos(dictn, &pos1);
}
}
printf("%s ", word);
}
fclose(inp);
fclose(dict);
return(0);
}
You can use
sprintf(word, "%s ", dictn);
If your code is working with printf it should work with sprintf, provided you don't overflow "word", including the NULL termination, so you might have to resize "word" if it is smaller than dictn.
First of all, I'm assuming you have created arrays word and dictn with enough size to hold the maximum length string any of your files.
First fault:
In loops you've created, i represents number of strings in input file and j represents number of strings in dictionary. word is your input string variable and dictn is your dictionary string variable. But you want to retrieve and alter word's ith or dictn's jth character. This may cause an error because there can be a case like this:
Suppose there are 10 words at inp file and 100 words at dictn. And in your loops, i have value of 8 and j have value of 88. Corresponding these i and j values, word has string value of, say, apple and dictn has string value of apple also. So this means apple is the 8th word at input file and 88th word at dictionary file. And if one of those if conditions was satisfied, compiler tries to apply a statement like word[i]=dictn[j];. This means word[8] = dictn[88]; for this example. But both of those string have apple as values which consists only 5 characters! And this will cause an error since you've tried to retrieve 88th character of a 5-length string and assign it to the 8th character of a 5-length string. So your code is wrong, it will only work for some cases which will be a rare situation.
Second fault:
I assume you want to read whole dictionary file for every word in input file but you will be able to read it for only first word of input file since you don't reopen it or set position indicator at the beginning of dictionary file after you read whole dictionary.
Third fault:
Your first if statement will never be reached assuming you have created len1 and len2 variables as integers. Because in your if statement, there is a multiplication of a decimal number and an integer which will return 0 as a result and since fscanf() ignores whitespaces, len1 and len2 will be at least 1.
Fourth fault:
Also your else if statement will never be reached because if a string has same value with another, their first character will also be equal to each other and your if statement where you compare their first characters will be also accepted.
Actually, I would write a code as solution but first of all you need to correct things up which are logically wrong because I do not know what you are really try to achieve by your code -just because I commented with full of assumptions-. But I can provide you some guidelines:
Convert your len1 and len2 variables from int to float and cast values which return from strlen() functions to float.
Reopen your dict file for every iteration of outside loop. (And do not forget not to close it).
To change your inp file, you can use a fpos_t type of variable to track your position indicator of your inp file (fgetpos() to get current position and fsetpos() to change position with value of fpos_t variable. You can search them.) and type the word with fprintf() or fputs() to that location to change that string.
I'm in the process of making a program that parses words from a line, adding a word to a tree when it hits an nonalphanumeric character. Everything goes fine when there are no spaces in a line. However, when there are nonalphanumeric characters, the loop in question (beginning at the line commented in the code) halves in size!
Why does the loop halve?
Tree addin (char* filee, Tree tree)
{
int i;
FILE *fp;
fp = fopen(filee, "r");
char* hold2 = malloc(99);
int count=-1;
char* hold;
while ((hold=getLine(fp))!=NULL)
{
count=-1;
for (i=0; i<strlen(hold); i++) //The loop in question
{
count++;
if ((isalnum(hold[count])==0)&&(hold[count]!='\n'))
{
strncpy(hold2, hold, count);
hold2[count]='\0';
hold=strdup(&hold[count+1]);
count=-1;
tree = insertT(tree, hold2);
}
}
tree = insertT(tree, hold);
}
free(hold);
fclose(fp);
return tree;
}
When you find a non-alphanumeric character, your program moves hold to point to the remainder of your string, but doesn't reset i. That means you continue iterating from the new hold pointer, which is partway into the original one, plus whatever i happened to be at that time. Doing so presumably at least skips a bunch of characters, and possibly makes you start operating on memory outside of the string, which is definitely bad news.
It may be because you change the value of hold within the loop, since strlen(hold) is reevaluated at each iteration. A solution could be to save the value of strlen(hold) before entering the for loop.
For the C project coming up, the goal is to read in a CSV file with the first two lines listing the row and column lengths like
attributes: 23
lines: 1000
e,x,y,n,t,l,f,c,b,p,e,r,s,y,w,w,p,w,o,p,n,y,p
e,b,y,y,t,l,f,c,b,n,e,c,s,s,w,w,p,w,o,p,n,s,m
e,x,f,y,t,l,f,w,n,w,t,b,s,s,w,w,p,w,o,p,n,v,d
e,s,f,g,f,n,f,c,n,k,e,e,s,s,w,w,p,w,o,p,k,v,u
The thing is, I don't know if future file inputs will be of the same row/column lengths, so I'm implementing a determineFormat function to read those first two lines, which will be used for building the data structures.
In order to do this, I need to match a substring to the current line. If it matches, then fscanf is used to read in the line and extract the length integers. However, this code isn't working, as the entire strstr function is getting skipped over in ddd.
int lineCount, attrCount; //global variables
void determineFormats(FILE *incoming){
char *curLine= emalloc(CLINPUT);
int i;
char *ptr=NULL;
for (i=0; i<2; i++){
if (fgets(curLine, CLINPUT, incoming) != NULL){
ptr= strstr(curLine, "attrib"); //this line is skipped over
if (ptr!= NULL)
fscanf(incoming, "attributes: %d", &attrCount);
else
fscanf(incoming, "lines: %d", &lineCount);
}
}
printf("Attribute Count for the input file is: %d\n", attrCount);
printf("Line count is: %d\n", lineCount);
}
My thinking for the if/else block is since there are only two lines of interest to this function, and they're both at the head of the file, just scan each line and test if the string matches. If it does, then the non-null conditional is run, otherwise the other conditional is executed. However, in this case, the strstr function is getting skipped.
Extra Info
Some of the comments made me go back and double check.
CLINPUT is defined to be 100, or roughly 40% again the number of characters to read from each line.
This is the output from ddd when ptr= strstr(curLine, "attrib"); is called:
0xb7eeaff0 in strstr () from /lib/libc.so.6
Single stepping until exit from function strstr,
which has no line number information.
Once this happens, the line indicator disappears, and single stepping (F5) from that point returns to the calling function.
strstr is working good. Problem is that fscanf will read next line since current already read.
Here's more correct way
for (i=0; i<2; i++){
if (fgets(curLine, CLINPUT, incoming) != NULL){
if (strstr(curLine, "attributes:")) {
sscanf(curLine, "attributes: %d", &attrCount);
} else if (strstr(curLine, "lines:")) {
sscanf(curLine, "lines: %d", &lineCount);
}
}
}