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.
Related
We have an assignment which is to take characters from a file, shift it a given value to the right(it'll make sense in the code) and then store that new value in a new file, but I seem to be running into a segmentation fault, which as far as I know means I'm trying to access memory outside of the memory I have been allocated? I'm very new to C and I managed to debug this code up until this point and I honestly don't know where to go. I don't even quite understand what the issue is.
#include<stdio.h>
//Get Shift amount
//Get ifilename
//Get ofilename
//open them
//Get characters one at a time from input
//Process and shift by shift amount
int main()
{
int i;//loop value
char a[62]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";//Variable with every value
int sa = 0;//Store Shift value
char ofile[30];//contain the name of output file
char ifile[30];//contain name of input file
char value;//Value to keep the current value in
printf("How far in ascii values would you like to shift?\n");
scanf("%i", sa);//Get shift
printf("What is the name of your input file located in this directory?");
scanf("%s", ifile);//get input name
printf("What would you like to name your new file?\n Do note that it will overwrite the current file named this!");
scanf("%s", ofile);//Get output name
FILE *oIfile = fopen(ifile, "r"), *oOfile = fopen(ofile, "w");
while(value = fscanf(oIfile, "%c", value) != EOF)//Check to ensure that you never reach the end of the file
{
for(i=0; i<62; i++)//loop through the list of all characters
{
if(value == a[i])//check to see if the value from the input file matches with which letter
{
value = a[i+sa] % 62;//incrase the value by the shift amount, check if its longer than 62, add remainder
break;//break the for loop so we can restart the while loop with the next letter
}
}
fprintf(oOfile, "%c");//print the new value to the output file
}
fclose(oIfile);//close input file
fclose(oOfile);//close output file
}
is this issue due to my approach to scanf?
Apart from passing the address to scanf (scanf("%i",&sa) which you would have to do (Also it would be correct to check the return value of it) - you need to correct a few things:-
It should be (value = fscanf(oIfile, "%c", value)) != EOF. != has higher precedence than = so this is needed to get the correct result.
Also a[(i+sa)%62]=... is the right way to do things. Because otherwise it will access array index out of bound for certain values of sa leading to undefined behavior.
fprintf(stream,"%c",charvariable) this would be the use for fprintf.
The value is over written with what is being returned by the value that fscanf returns. You should use other temporary variable or even better simply do like this while(fscanf(oIfile, "%c", value)!=EOF). But to have more checks you need to do somehting like
int c;
while((c=fscanf(oIfile, "%c", value))!=EOF)
You got segmentation fault here by passing the value of sa instead of its address in scanf.
scanf take an address as a parameter. Try this;
scanf("%i", &sa);//Get shift
I am trying to create a program that take the input from the user and prints the first character of each word but every time I try to Here is my code.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
int main(void)
{
char leng[100];
int len;
scanf("%s", &leng[100]);
len = strlen(&leng[100]);
char name[len];
//checking if at end or not
while (name[len] != '\0')
{
if (name[len] == ' ')
printf("%c", name[len + 1]);
len++;
}
}
Every time I give a name it shows an error something like:
index 3 out of bounds for type 'char [len]'
These two lines are incorrect:
scanf("%s", &leng[100]);
len = strlen(&leng[100]);
If you translate these into English, their meanings as written are:
Scan a string to the memory at the address of 101st element of the
leng array.
Get the length of the string that starts at the address
of the 101st element of the leng array.
The array index is out of bounds because leng[100] is past the end of the array. Remember that a 100 element array goes from 0 to 99, not from 1 to 100!
You want to be scanning into the base address of the array, and passing the base address of the array into strlen(). I'll leave the syntax for you to figure out from your textbook.
And by the way, you also have a problem in your code because you're reading your data into an array named leng, but your loop is working with an array named len. There are at least two additional problems in your code, but I'll leave them for you to debug.
There are a few things to consider with your code. As #richardschwartz already mentioned, you are not referencing your char arrays correctly. you have:
scanf("%s", &leng[100]);
len = strlen(&leng[100]);
You may want the following instead:
scanf("%s", leng);
len = strlen(leng);
Also, keep in mind that scanf with the %s flag will stop reading input once white-space is detected. For example, if you input "hello world",
scanf("%s", leng);
will only catch the characters "hello". To get around this, you could loop scanf to read multiple words and return the first character of each word as you desire.
Lastly, scanf is not advised for beginners though. See paxdiablo's excellent reason regarding lack of overflow protection, here: https://stackoverflow.com/a/1248017/6870832
I'm trying to find the total number of lines in a text file, but it's not working (the final line count is 0 - see below). Here's the code:
#define BUFFER_SIZE 1
int lineNumber = 0;
int columnNumber = 0;
char *byteCurrent;
while (read(openFile, &byteCurrent, BUFFER_SIZE) > 0)
{
if (byteCurrent[0] != '\0') columnNumber++;
if (byteCurrent[0] == '\n') lineNumber++;
printf("%c", byteCurrent);
}
You have many problems with this code. The first is that you have an uninitialized pointer byteCurrent, but that doesn't matter since you don't actually use what it points to (which is just some seemingly random location) but you use a pointer to the pointer. When you do &byteCurrent you get a pointer to the variable byteCurrent which is of type char **.
That's just one problem, another is that there is no string terminator in a file. If you get a zero when reading (which is what '\0' is) it's because there is an actual zero in the file, not because you get to the end of something. This leads columnNumber to count the number of characters in the file and not any column number.
The solution to the first problem is to use a plain char variable:
char byteCurrent;
The solution to the second problem I don't know, because I don't know what your columnNumber variable is supposed to count.
I am trying to write a simple piece of code to read values from a CSV file with a max of 100 entries into an array of structs.
Example of a line of the CSV file:
1,Mr,James,Quigley,Director,200000,0
I use the following code to read in the values, but when I print out the values they are incorrect
for(i = 0; i < 3; i++) /*just assuming number of entries here to demonstrate problem*/
{
fscanf(f, "%d,%s,%s,%s,%s,%d,%d", &inArray[i].ID, inArray[i].salutation, inArray[i].firstName, inArray[i].surName, inArray[i].position, &inArray[i].sal, &inArray[i].deleted);
}
Then when I print out the first name, the values are all assigned to the first name:
for(j = 0; j < 3; j++) /* test by printing values*/
{
printf("Employee name is %s\n", inArray[j].firstName);
}
Gives ames,Quigley,Director,200000,0 and so on in that way. I am sure it's how i format the fscanf line but I can't get it to work.
Here is my struct I'm reading into:
typedef struct Employee
{
int ID;
char salutation[4];
char firstName[21];
char surName[31];
char position[16];
int sal;
int deleted;
} Employee;
This is because a string %s can contain the comma, so it gets scanned into the first string. There's no "look-ahead" in the scanf() formatting specifier, the fact that the %s is followed by a comma in the format specification string means nothing.
Use character groups (search the manual for [).
const int got = fscanf(f, "%d,%[^,],%[^,],%[^,],%[^,],%d,%d", &inArray[i].ID,
inArray[i].salutation, inArray[i].firstName,
inArray[i].surName, inArray[i].position, &inArray[i].sal,
&inArray[i].deleted);
And learn to check the return value, since I/O calls can fail! Don't depend on the data being valid unless got is 7.
To make your program read the entire file (multiple records, i.e. lines), I would recommend loading entire lines into a (large) fixed-size buffer with fgets(), then using sscanf() on that buffer to parse out the column values. That is much easier and will ensure that you really do scan separate lines, calling fscanf() in a loop will not, since to fscanf() a linefeed is just whitespace.
Might as well post my comment as an answer:
%s reads a full word by default.
It finds the %d, the integer part, then the ,, and then it has to read a string. , is considered valid in a word (it is not a whitespace), so it reads until the end of the line (there is no whitespace until then), not until the first comma... And the rest remains empty. (From this answer)
You have to change the separator with specifying a regex:
fscanf(f, "%d,%[^,],%[^,],%[^,],%[^,],%d,%d", &inArray[i].ID, inArray[i].salutation, inArray[i].firstName, inArray[i].surName, inArray[i].position, &inArray[i].sal, &inArray[i].deleted);
Instead of %s, use %[^,], which means "grab all chars, and stop when found a ,".
EDIT
%[^,]s is bad, it would need a literal s after the end of the scanset... Thanks #MichaelPotter
(From Changing the scanf() delimiter and Reading values from CSV file into variables )
I am completely new to C and need help with this badly.
Im reading a file with fopen(), then obtaining the contents of it using fgetc(). What I want to know is how I can access the line fgetc() returns so if I can put the 4th - 8th characters into a char array. Below is an example I found online but am having a hard time parsing the data returns, I still don't have a firm understanding of C and don't get how an int can be used to store a line of characters.
FILE *fr;
fr = fopen("elapsed.txt", "r");
int n = fgetc(fr);
while(n!= EOF){
printf("%c", n);
n = fgetc(fr);
} printf("\n");
Here
1 first open the file
2 get size of file
3 allocated size to character pointer
4 and read data from file
FILE *fr;
char *message;
fr = fopen("elapsed.txt", "r");
/*create variable of stat*/
struct stat stp = { 0 };
/*These functions return information about a file. No permissions are required on the file itself*/
stat("elapsed.txt", &stp);
/*determine the size of data which is in file*/
int filesize = stp.st_size;
/*allocates the address to the message pointer and allocates memory*/
message = (char *) malloc(sizeof(char) * filesize);
if (fread(message, 1, filesize - 1, fr) == -1) {
printf("\nerror in reading\n");
/**close the read file*/
fclose(fr);
/*free input string*/
free(message);
}
printf("\n\tEntered Message for Encode is = %s", message);
PS Dont Forget to Add #include <sys/stat.h>.
You're not retrieving a line with fgetc. You are retrieving one character at a time from the file. That sample keeps retrieving characters until the EOF character is encountred (end of file). Look at this description of fgetc.
http://www.cplusplus.com/reference/clibrary/cstdio/fgetc/
On each iteration of the while loop, fgetc will retrieve a single character and place it into the variable "n". Something that can help you with "characters" in C is to just think of it as one byte, instead of an actual character. What you're not understanding here is that an int is 4 bytes and the character is 1 byte, but both can store the same bit pattern for the same ASCII character. The only different is the size of the variable internally.
The sample you have above shows a printf with "%c", which means to take the value in "n" and treat it like an ASCII character.
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
You can use a counter in the while loop to keep track of your position to find the 4th and 8th value from the file. You should also think about what happens if the input file is smaller than your maximum size.
Hope that helps.
Ok look at it as box sizes I could have a 30cm x 30cm box that can hold 1 foam letter that I have. Now the function I am calling a function that 'could' return a 60cm x 60cm letter but it 99% likely to return a 30cm x 30cm letter because I know what its reading - I know if I give it a 60cm x 60cm box the result will always fit without surprises.
But if I am sure that the result will always be a 30cm x 30cm box then I know I can convert the result of a function that returns aa 60cm x 60cm box without losing anything