read text file and store in array in c programming - c

I want read text file and store in array then show.
This is my code:
int i = 0, line = 5;
char ch[100];
FILE *myfile;
myfile = fopen("test.txt","r");
if (myfile== NULL)
{
printf("can not open file \n");
return 1;
}
while(line--){
fscanf(myfile,"%s",&ch[i]);
i++;
printf("\n%s", &ch[i]);
}
fclose(myfile);
return 0;
}
This is my text:
test 123562
856
59986
But result:
est
2356
56
9986
What is wrong? :(

ch[i] is holding a single character. Statement fscanf(myfile,"%s",&ch[i]); will scan string to ch[i] which can hold only one character. There is no place for '\0' which leads your program to undefined behavior.
Change
fscanf(myfile,"%s",&ch[i]);
to
fscanf(myfile,"%s",ch);
Previous answer was wrong. Behavior of program is well defined but you are scanning the file in a wrong manner. Your program will work as expected if you place i++; after printf statement.
while(line--){
fscanf(myfile,"%s",&ch[i]);
printf("\n%s", &ch[i]);
i++;
}
The reason is that &ch[i] is a pointer to the ith element of the array and string will be stored in array starting at position i. For the input given, this will work because the given array is large enough to hold the string.
You can do this as:
while(line--){
fscanf(myfile,"%s",ch);
printf("\n%s", ch);
i++;
}
but it will overwrite the array ch each time a string is scanned to it. Better to use a two dimensional array to store strings and read file with fgets.

You're not going to be able to fit five lines in the single char ch[100] array; that's just an array of 100 characters.
You can make it an array of arrays, i.e. char ln[5][100] which will give you room for five lines of 100 characters each.
Then you of course need to index into that array in the loop, i.e.:
for(int i = 0; i < 5; ++i)
{
if(fgets(ln[i], sizeof ln[i], myfile) == NULL)
{
fprintf(stderr, "Read error on line %d\n", i);
exit(1);
}
}
This uses fgets() which is much better suited at reading in whole lines; fscanf() will stop at whitespace with %s which is seldom what you want.

There is no need to use the ampersand in the scanf while getting the string. Make that into like this.
fscanf(myfile,"%s",&ch[i]);
to
fscanf(myfile,"%s",ch);
&ch[i] It will get the character for i th position in that array. If you want to get like that you can use the %c instead of %s. And change this one to.
printf("\n%s", ch);
While printing the string when you use the ampersand(&) that will access the address of that variable.

The program developed must be able to read the input files containing matrix A and matrix B
using fopen function
a. Matrix A and B of different size may be stored in different input file (if required).
Scan and assign matrix A and B as array using fscanf function and for loop
Perform matrix operations
a. Add matrix A and B
b. Subtract matrix A and B
c. Multiply matrix A and B
Use conditional statement if or switch for switching between 3, 4 and 5 elements matrix.
Print all input matrices and results obtained in a new file called output.dat using fprintf
function.
The output.dat file must have a header with the following information:
a. Student name
b. Student matric number
c. Class section
d. Lecturer name
e. Project title
Below the header, the output file must contain matrix A and B and the results from matrix
operation.
Use matrix A and B as given below:

Related

How do I read the contents of a file in C and store it into an array using fgets()?

So I need to create a word search program that will read a data file containing letters and then the words that need to be found at the end
for example:
f a q e g g e e e f
o e q e r t e w j o
t e e w q e r t y u
government
free
and the list of letters and words are longer but anyway I need to save the letters into an array and i'm having a difficult time because it never stores the correct data. here's what I have so far
#include <stdio.h>
int main()
{
int value;
char letters[500];
while(!feof(stdin))
{
value = fgets(stdin);
for(int i =0; i < value; i++)
{
scanf("%1s", &letters[i]);
}
for(int i=0; i<1; i++)
{
printf("%1c", letters[i]);
}
}
}
I also don't know how I am gonna store the words into a separate array after I get the chars into an array.
You said you want to read from a data file. If so, you should open the file.
FILE *fin=fopen("filename.txt", "r");
if(fin==NULL)
{
perror("filename.txt not opened.");
}
In your input file, the first few lines have single alphabets each separated by a space.
If you want to store each of these letters into the letters character array, you could load each line with the following loop.
char c;
int i=0;
while(fscanf(fin, "%c", &c)==1 && c!='\n')
{
if(c!=' ')
{
letters[i++]=c;
}
}
This will only store the letters and is not a string as there is no \0 character.
Reading the words which are at the bottom may be done with fgets().
Your usage of the fgets() function is wrong.
Its prototype is
char *fgets(char *str, int n, FILE *stream);
See here.
Note that fgets() will store the trailing newline(\n) into string as well. You might want to remove it like
str[strlen(str)-1]='\0';
Use fgets() to read the words at the bottom into a character array and replace the \n with a \0.
and do
fgets(letters, sizeof(letters, fin);
You use stdin instead of the fin here when you want to accept input from the keyboard and store into letters.
Note that fgets() will store the trailing newline(\n) into letters as well. You might want to remove it like
letters[strlen(letters)-1]='\0';
Just saying, letters[i] will be a character and not a string.
scanf("%1s", &letters[i]);
should be
scanf("%c", &letters[i]);
One way to store the lines with characters or words is to store them in an array of pointers to arrays - lines,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLET 500
#define MAXLINES 1000
int main()
{
char *lptr;
// Array with letters from a given line
char letters[MAXLET];
// Array with pointers to lines with letters
char *lineptr[MAXLINES];
// Length of current array
unsigned len = 0;
// Total number of lines
int nlines = 0;
// Read lines from stdin and store them in
// an array of pointers
while((fgets(letters,MAXLET,stdin))!=NULL)
{
len = strlen(letters);
letters[len-1] = '\0';
lptr = (char*) malloc(len);
strcpy(lptr, letters);
lineptr[nlines++]=lptr;
}
// Print lines
for (int i = 0; i < nlines; i++)
printf("%s\n", lineptr[i]);
// Free allocated memory
for (int i = 0; i < nlines; i++)
free(lineptr[i]);
}
In the following, pointer to every line from stdin is stored in lineptr. Once stored, you can access and manipulate each of the lines - in this simple case I only print them one by one but the examples of simple manipulation are shown later on. At the end, program frees the previously allocated memory. It is a good practice to free the allocated memory once it is no longer in use.
The process of storing a line consists of getting each line from the stdin, collecting it's length with strlen, stripping it's newline character by replacing it with \0 (optional), allocating memory for it with malloc, and finally storing the pointer to that memory location in lineptr. During this process the program also counts the number of input lines.
You can implement this sequence for both of your inputs - chars and words. It will result in a clean, ready to use input. You can also consider moving the line collection into a function, that may require making lineptr type arrays global. Let me know if you have any questions.
Thing to remember is that MAXLET and especially MAXLINES may have to be increased for a given dataset (MAXLINES 1000 literally assumes you won't have more than a 1000 lines).
Also, while on Unix and Mac this program allows you to read from a file as it is by using $ prog_name < in_file it can be readily modified to read directly from files.
Here are some usage examples - lineptr stores pointers to each line (array) hence the program first retrieves the pointer to a line and then it proceeds as with any array:
// Print 3rd character of each line
// then substitute 2nd with 'a'
char *p;
for (int i = 0; i < nlines; i++){
p = lineptr[i];
printf("%c\n", p[2]);
p[1] = 'a';
}
// Print lines
for (int i = 0; i < nlines; i++)
printf("%s\n", lineptr[i]);
// Swap first and second element
// of each line
char tmp;
for (int i = 0; i < nlines; i++){
p = lineptr[i];
tmp = p[0];
p[0] = p[1];
p[1] = tmp;
}
// Print lines
for (int i = 0; i < nlines; i++)
printf("%s\n", lineptr[i]);
Note that these examples are just a demonstration and assume that each line has at least 3 characters. Also, in your original input the characters are separated by a space - that is not necessary, in fact it's easier without it.
The code in your post does not appear to match your stated goals, and indicates you have not yet grasp the proper application of the functions you are using.
You have expressed an idea describing what you want to do, but the steps you have taken (at least those shown) will not get you there. Not even close.
It is always good to have a map in hand to plan to plan your steps. An algorithm is a kind of software map. Before you can plan your steps though, you need to know where you are going.
Your stated goals:
1) Open and read a file into lines.
2) Store the lines, somehow. (using fgets(,,)?)
3) Use some lines as content to search though.
4) Use other lines as objects to search for
Some questions to answer:
a) How is the search content distinguished from the strings to search
for?
b) How is the search content to be stored?
c) How are the search words to be stored?
d) How will the comparison between content and search word be done?
e) How many lines in the file? (example)
f) Length of longest line? (discussion and example) (e & f used to create storage)
g) How is fgets() used. (maybe a google search: How to use fgets)
h) Are there things to be aware of when using feof()? (discussion and examaple feof)
i) Why is my input not right after the second call to scanf? (answer)
Finish identifying and crystallizing the list of items in your goals, then answer these (and maybe other) questions. At that point you will be ready to start identifying the steps to get there.
value = fgets(stdin); is a terrible expression! You don't respect at all the syntax of the fgets function. My man page says
char *
fgets(char * restrict str, int size, FILE * restrict stream);
So here, as you do not pass the stream at the right place, you probably get an underlying io error and fgets returns NULL, which is converted to the int 0 value. And then the next loop is just a no-op.
The correct way to read a line with fgets is:
if (NULL == fgets(letters, sizeof(letters), stdin) {
// indication of end of file or error
...
}
// Ok letters contains the line...

Reading data from file to struct using fread

I'm writing a piece of code and a part of it is reading "records" from file to n-length array, n given as an argument. Records in file have constant length(in this case 1024) and contain only numerics, spaces and lower letters. Each record is terminated with \n. I'm using following structure to keep one record:
typedef struct{
char rec[1024];
} record;
And Code for extracting n of them and storing in n-length array of records is written this way:
record * recs=malloc(n*sizeof(record));
size_t read=fread(recs,sizeof(record),(size_t)n,f);
When I checked output of this operations it turns out that first element of array recs contains all of the records, second all but first and so on instead of keeping one at each element of array. I'm kind of lost, because i thought that it should store each record in different element of array.
As suggested, I'm also providing code for opening a file and printing elements of array:
if((f=fopen(argv[2],"r"))==NULL){
perror("error opening file\n");
exit(1);
}
for(int i=0;i<(int)read;i++){
printf("record number %d\n %s\n",i,recs[i].rec);
}
The problem is that your records rec isn't a zero terminated string.
So printing using %s shows all records because the printing will just continue until it sees a '\0'.
So either make sure to add a zero-termination in each rec or use another way of printing than %s.
BTW: If there isn't any zero-termination inside recs you actually have undefined behavior.
This little program mimics the problem:
#include <stdio.h>
struct r {
char c[1];
};
int main(void) {
int i;
struct r recs[4] = {{'a'}, {'b'}, {'c'}, {'\0'}};
// ^^^^^
// Just to stop printing here
for (i=0; i<3; i++)
{
printf("%d %s\n", i, recs[i].c);
}
return 0;
}
Output:
0 abc
1 bc
2 c

How to compare a specific string with all elements of an array in C?

I'm reading in from a file that has a hex value on each line. It will look like this:
F0BA3240C
083FA52
45D3687AF
etc.
The hex values won't have the same length.
I have fgets reading from this file into a buffer and then a piece of code to get rid of the newline character. From there I put the string from the buffer into my data array. But before putting the string from the buffer into my data array, I'm attempting to compare the string from the buffer to the strings already stored in the data array and see if there is or isn't a match so I can update some counters. However, I'm having issues using strcmp and strncmp. Any help will be appreciated, thanks.
Relevant code:
char **data = NULL;
char data_buffer[100];
//program first goes through the file and determines amount of lines there are hence this variable
int count_line = 0;
...
data = malloc(count_line * sizeof(char *));
int f;
int i;
for(i=0; i<count_line; i++)
{
fgets(data_buffer, sizeof(data_buffer), fp);
...
//allocate space to store copy of line and add one for null terminator
data[i] = malloc(line_length + 1);
...
if(asdf != NULL)
{
//problem here. don't know how to compare stream from buffer and compare to all elements of data buffer
for(f=0; f<sizeof(data); f++)
{
if(strcmp(data[f], data_buffer) == 0)
there_was_a_match++;
}
}
...
//copy string from buffer into data array
strcpy(data[i], data_buffer);
}
Consider these lines:
for(f=0; f<sizeof(data); f++)
{
if(strcmp(data[f], data_buffer) == 0)
there_was_a_match++;
}
What is the value of sizeof(data)? Since data is of type char**, presumably
sizeof(data) is the size of a pointer in bytes, so some fixed integer value such as 4 or 8.
Now observe that the first time you encounter this loop within the "for i" loop,
i is 0 and data[0] is the only pointer in the array of pointers that has been allocated--
every other pointer in data is invalid.
So now what happens is, we do the first iteration of the inner loop: f is 0, so we
end up comparing the string we just read to itself.
On the next iteration, f is 1, we try comparing our latest string to data[1],
but data[1] has not yet been initialized,
ergo we have undefined behavior (such as a crash).
You might be better off if the f loop were like this:
for(f=0; f<i; ++f)
{
if(strcmp(data[f], data_buffer) == 0)
there_was_a_match++;
}
This way, you will compare the newest string (which you have just saved in data[i])
with only the strings that were already loaded.
There is one other thing that may be troublesome. Suppose your input consists of four
copies of the same string.
Then after you read the second copy and execute this loop, there_was_a_match will be 1;
after reading the third copy and executing that loop, there_was_a_match will be 3
(because it matches twice);
after reading the fourth copy and executing that loop, there_was_a_match will be 6.
I suspect these are not the results you want.
Perhaps you want to break out of the loop after finding the first match.
I can´t see problems with strcmp/strcpy, but:
for(f=0; f<sizeof(data); f++)
You can´t use sizeof, ie. it won´t result in the value count_line.
From the shown code, this could be enough to make it work.
Just compare to the previous allocated lines, which is i lines.
// for(f=0; f<sizeof(data); f++)
for(f=0; f<i; f++)

Read whole digits not split

Hi guys how to read entire digits from file? I mean my input file is 100-4/2 and i wrote this code while(fscanf(in,"%s",s)!=EOF) but it read like this 1 0 0. I want read like 100. How to solve this?
It's probably because you are using one-byte character(ANSI) set while the file is written with two-byte characters(Unicode). If you have created the file with the same program that is reading it it's going to read it right, but if not, you can open the file you are reading in notepad, then click save as, and there you can choose ANSI or Unicode.
You can read the whole line at once using getline() or similar method (also you can read as you are doing if there is only one line, then when EOF is true, whole line is read). Then you can parse the line to extract numbers and operators.
Use "%d" for integers
int value;
if (scanf("%d", &value) != 1) /* error */;
printf("Value read is %d.\n", value);
The below is simple program is self explanatory, which reads a file character by character, for each iteration stores this character into a temporary variable temp. and when the value in temp is a numerical character it simply copies this value in array named s.
int main()
{
char s[10]="\0";//initialzing array to NULL's and assuming array size to be 10
int i=0,temp=0;
FILE *fp=fopen("t.txt","r"); //when file has 100-4/2
if(fp==NULL)
{
printf("\nError opening file.");
return 1;
}
while( (temp=fgetc(fp))!=EOF && i<10 ) //i<10 to not exceed array size..
{
if(temp>='0' && temp<='9')//if value in temp is a number (simple logic...)
{
s[i]=temp;
i++;
}
}
printf("%s",s);//outputs 10042
return 0;
}

Replace value in string with another from another string

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.

Resources