I am trying to read a series of names from a text file and save them into an array.
Everything looked okay until I try to reference a specific name by using indexes (ex: array[0] ). It gives me t25.txt where it should of give me t1.txt. What did I do wrong?
Here's what I have:
#define MAX_STRING 25
FILE *in;
in = fopen("filenames.txt", "r");
if (!in) {
printf("Failed to open the file\n");
exit(1);
}
char array[MAX_STRING];
// In my mind, I want it to look like this:
// array[0] = t1.txt
// array[1] = t2.txt
int i;
for ( i = 0; i < MAX_STRING; i++ ) // Get 25 words
{
fscanf( in, "%s", array);
printf( "filename = %s\n", array);
// I print it out to make sure it's getting what i want and it did
}
My text file - filenames.txt is something like this
t1.txt
t2.txt
Thanks much
char array[MAX_STRING];
is an array of characters, not an array of strings. Your loop overwrites this array in every iteration. You might have meant something like
char array[N_STRINGS][MAX_LENGTH_OF_A_SINGLE_STRING];
You aren't saving multiple strings in one array, you are overwriting one string multiple times.
In C each string is saved as an array, so you have to have something like a 2D-Array: Dimension 1: the String, Dimension 2: The "array":
array[MAX_STRING][MAX_NAME_LEN]
This is what you intend to do!
You have to understand C-Strings as an Array of Characters in continous memmory, with a \0 at the end to identify the end of the "string". You are handling with arrays when you are handling with strings!
you define char array[MAX_STRING]; which simply defines one string
so
array[0] = 't'
array[1] = 'x'
What you need is char array[NUM_STRING][MAX_STRING]
Related
Newbie here. I need to create a program that reads strings from a textfile.txt then processes a few characters from it.
The contents of textfile.txt is as below.
JA100200300
FE111222333
MA101202303
I need to reference "JA","100", "200" and "300" separately. I managed to do this with the code below, where I split the string into 11 characters and put it into array. Of course this code works only as you type out the string. I need a way to do the same thing but get the string from a file instead.
while((a[i++]=getchar()) != '\n' && i < 11);
How do I do this? Can I read the file and put each line of string into an array, then read from the array and split each array into multiple arrays? Is that possible? Or read each character from the file and put them into arrays something like fscanf %d but split each character?
You might want something like this:
FILE fp = fopen("data.txt","r");
char line[100] = { 0 }, str1[3], str2[4], str3[4], str4[4];
if (!fp) {
perror("opening file");
exit(1);
}
while(fgets(line,sizeof line,fp)) {
strncpy(str1,line,2);
str1[2] = '\0';
strncpy(str2,&line[2],3);
str2[3] = '\0';
strncpy(str3,&line[5],3);
str3[3] = '\0';
strncpy(str4,&line[8],3);
str4[3] = '\0';
}
Example file:
School Name (with spaces)
FirstNameofStudent StudentID
School Name2 (with spaces)
FirstNameofStudent2 StudentID2
School Name3 (with spaces)
FirstNameofStudent3 StudentID3
I cant seem to figure out what to do after using fgets for the first line.
If by itself, I can easily get school name using fgets
and the second line by itself using fscanf then converting the studentID to int using atoi.
But how do I combine both fgets and fscanf?
The information scanned would be placed into an array.
Before I go onto the solution, I want to point out that an array can only have a single type. You cannot store integers in an array of characters.
Meaning if you would like all of this information to go in a single 2D array, you'd need to store the ID as a string. Then if you need it as an integer, you'd need to use atoi on it once you retrieve it.
Now for combining the two, you'd need a while loop with fgets in the condition in order to retrieve the first line. Something like this:
while(fgets(schoolname, 255, fp) != 0){ ... }
This would keep on retrieving lines until it fails, or it reaches EOF. However, you wanted to use fscanf for the second line, and for that, you'd need a line like this:
fscanf(fp, "%s %s\n", name, id);
This means, from the current point, there are two strings seperated by a space, and a newline. Store the two strings in name and id, and gobble the newline.
Gobbling the newline is key, as if you don't do it, the next time fgets runs, it would only find a single newline on the line.
As for storing the elements in an array, you'd need a 2D array of strings. For that, you can either do it fixed, or dynamic. For fixed, it's pretty easy, just have a line like char students[3][3][80] and simply store stuff in there, but for dynamic, you'd need to use memory allocation, pointers, etc, with a variable liks char ***students
Here's the code I used to solve your problem, though I suggest trying to do this on your own as well, to get the hang of it:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
FILE *fp = fopen("ex.txt", "r");
if(fp == 0) exit(-1);
char ***students;
// Used to check how many students there are
int studentno = 0;
// Init students array
// So far it means 1 ROW, with 3 COLUMNS, each of 80 CHARACTERS
students = calloc(studentno+1, 3 * 80);
// Temporary variables for storage
char schoolname[80];
char name[20];
char id[10];
int i = 0;
while(fgets(schoolname, 255, fp) != 0){
studentno++;
// Retrieve name and id from second line
fscanf(fp, "%s %s\n", name, id);
// Cut off newline left from fgets
schoolname[strlen(schoolname)-2] = 0;
// Allocate memory for new members of array
students[i] = malloc(3 * 80);
students[i][0] = malloc(80);
students[i][1] = malloc(80);
students[i][2] = malloc(80);
// Copy strings received into array
strcpy(students[i][0], schoolname);
strcpy(students[i][1], name);
strcpy(students[i][2], id);
// Resize students array for additional students
students = realloc(students, (size_t) (studentno+1) * 3*80);
i++;
}
// Check students are stored correctly
for(int i = 0; i < studentno-1; i++){
printf("%s - %s - %s\n", students[i][0], students[i][1], students[i][2]);
}
}
So, I'm attempting to scan in a large number of words from a text file and store them in a manner that allows them to be accessible from a single array.
149256
aahing
aahs
aals
aardvark
aardvarks
aardwolf
aardwolves
aargh
aarrgh
aarrghh
I'm scanning these words from a text file in the above format. The number is the total number of words(it's a dictionary, explains the high word count) present in the list, and the words follow a line at a time. I'd like to be able to access each individual word from a dynamically allocated array i.e. word[0] will contain "aahing". Now I know a simple char array is unable to accomplish this. I first attempted to accomplish this with a multidimensional array in the below code:
main(){
int numWords,i;
FILE * fp= fopen("dictionary.txt","r");
fscanf(fp,"%d", &numWords);
char* array = malloc(numWords * 20 * sizeof(char)); //word length is always below 20
for(i = 0; i < numWords; i++){
fscanf(fp, "%s", &array[i]);
//printf("%s \n",&array[i]); used to check the scan
}
printf("%s \n",&array[0]);
}
*The & infront of the array shouldnt be needed by my understadning, but the program crashes when these are not present, probably a problem with my code.
Now when removing the final printf statement and uncommenting the printf in the loop, the program seems to work as it is meant to. But, if you add the last printf,the program prints the first letter of every single word scanned along with the entirety of the last word. From my understanding this shouldn't be possible as each new word should have been scanned into a different row of the array, but obviously this is not the case. In this instance would I be better of somehow assigning each slot of an array to point towards a new array in each slot? i.e. array[1] -> data[] , array[2] -> data[] each of which would contain a new word.
A point in the right direction would be greatly appreciated.
It's printing the first letter of every word because you're only advancing one index every loop. If you add foo to the address array[0], the next word should start at array[3], so what you have to do is instead of &array[i], keep count of how many chars were already written and add to that index, like so:
int chars_written = 0;
for(i = 0; i < numWords; i++){
fscanf(fp, "%s", &array[chars_written]);
//printf("%s \n",&array[chars_written]); used to check the scan
chars_written += strlen(&array[chars_written])
}
If you wanna, however, have an array of strings, where every index is a string, you need a different filetype:
char **array;
Since a string is an array of chars, so you need an array of arrays of chars.
And then you need to allocate it and use it like so:
char **array;
array = malloc(sizeof(char*) * (numWords + 1))
for (int i = 0, i < numWords; i++)
array[i] = malloc(sizeof(char) * 20); // assuming every word is under 19 chars (you used 20 in your code, thats why i used it)
array[numWords] = NULL;
for(i = 0; i < numWords; i++){
fscanf(fp, "%s", array[i]);
//printf("%s \n",array[i]); used to check the scan
}
Can someone please help explain the difference in C and how my file fails to merge, and appends instead? The background is I am on an online computer science class this summer which uses C language, all we are given is read the entire texbook (732 pages), and do 20 projects over the course of 8 weeks, with no actual instruction, lecture, slides, or explanations. Please explain it so I can learn as I need to actually understand these terms to be better and progress in my Electrical Engineering program. I have contacted my professor for help but the answers are always short and uninformative, and you guys have provided so much more quality feedback to date. Also I do get that he is right and it was appended and not merged, but any feedback how i could of rectified this will help as well. Thank you again!
#include <stdio.h>
#include <stdlib.h>
FILE *inptr1, *inptr2, *outptr;
int main()
{
char c;
char file1[30], file2[30], file3[30];
printf("Enter the first files name\n");
gets(file1);
printf("Enter the second files name\n");
gets(file2);
printf("Enter the file name that will store the data from the other two files\n");
gets(file3);
inptr1 = fopen("C:\\Users\\Eric\\Desktop\\file1.txt","r");
inptr2 = fopen("C:\\Users\\Eric\\Desktop\\file2.txt","r");
if( inptr1 == NULL || inptr2 == NULL )
{
perror("Error ");
printf("Press any key to exit!\n");
exit(1);
}
outptr = fopen("C:\\Users\\Eric\\Desktop\\file3.txt","w");
if( outptr == NULL )
{
perror("Error ");
printf("Press any key to exit!\n");
exit(1);
}
while( ( c = fgetc(inptr1) ) != EOF )
fputc(c,outptr);
while( ( c = fgetc(inptr2) ) != EOF )
fputc(c,outptr);
printf("The two files were sucessfully merged into %s \n",file3);
fclose(inptr1);
fclose(inptr2);
fclose(outptr);
return 0;
}
Page 611 #5 Write a complete C program. Use the two files provided. Your program should not assume that you know which file is shorter.
5) Write a function to merge two sorted files of names and write the names to a
new file.
Was the only direction I was given as far as to what the program was supposed to do.
and this was the feedback i received, "Did you look at the resulting file?The girls names are all at the bottom. You were to merge the files,not append the files."
Thank you again in advance for your valuable feedback as it has taught me so much to date.
You're going to need to look at the contents of each file and write them to the third file in sorted order. That seems to be what the assignment is asking you to do. What you're doing currently is dumping the contents of file1.txt into file3.txt followed by the contents of file2.txt. You want to end up with a sorted list containing the contents of both files.
There are many ways to accomplish your requirements. This is just one that jumps out:
Steps to perform:
1 Open two existing files (fopen(fp, "r");), and one new file (fopen(fp, "w");)
2 write all lines of first file, then the second file to the third file. (fopen(), fgets(), fputs(), fclose(), etc.)
3 Read third file into an array of strings, keeping a count of the total number of strings read. close file.
4 Sort array of strings. (qsort())
5 Open third file, Write sorted array of strings into that file.
6 Close all files, free all memory.
Note, using this method, it does not matter if the two original files are sorted, or not, (Assignment says they are, but does not matter). The qsort routine will completely sort the string array either way.
qsort()
Most of the functions referenced are straight forward to use. qsort() is a little weird.
Here is an example showing how to set up qsort() for use sorting an array of strings:
For an array of strings: strings with the number of strings being say: cnt then:
qsort(strings, cnt, sizeof(char*), sortstring);
//With the function sortstring defined as:
static int sortstring( const void *str1, const void *str2 )
{
const char *rec1 = *(const char**)str1;
const char *rec2 = *(const char**)str2;
int val = strcmp(rec1, rec2);
return val;
}
string arrays
Creating an array of strings can also be challenging. Again, there are several ways to do this, here are two:
If you know the dimensions of each line, and the total number of lines in both files, then you can do it like this:
char strArray[numLines][longestLine];
If you don't, then you have to determine that at run-time by getting a count of the total number of lines, say when you are reading them from each file. And you will also need the length of the longest line found in both files, say by using strlen() on each one at some point as it is read or written. Once you have that information, you can create your string array like this:
char **strings=0;
Then, before you need it, create memory for it:
char **allocMemoryStr(char **strings, int numStrings, int maxLen)
{
int i;
strings = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
for(i=0;i<numStrings; i++)
{
strings[i] = calloc(sizeof(char)*maxLen + 1, sizeof(char));
}
return strings;
}
Finally, when you are finished using dynamically allocated memory, you must always free it:
void freeMemoryStr(char **strings, int numStrings)
{
int i;
for(i=0;i<numStrings; i++)
if(strings[i]) free(strings[i]);
free(strings);
}
I have a text file with 25 lines, each with 34 characters on.
In C how is it possible to load these characters and store them into a 2D array?
If the first three lines of the file are such:
bamaaaaaaaacxxxxxxxxxxbaaaaaaaamac
jzjzzzzzzzzdaaaaaaaaaaezzzzzzzzjzj
jzjzbaaczgzzzzzzzzzzzzzzgzbaaczjzj
...and so on
I require the array to be stored as if it was defined like this:
char* data[] = {
"baaaaaaaaaaaaaacxxbaaaaaaaaaaaaaac",
"jzzzzzzzzzzzzzzjxxjzzzzzzzzzzzzzzj",
"jzbaaaaaaaaaaaaexxdaaaaaaaaaaaaczj",
...and so on
Hopefully this makes some sense! It is important that the type of data is char data[][] as it is used in that format in the rest of my project and cannot be changed.
I have done the basic begining of the File IO
FILE *infp;
printf("Opening file\n");
if((infp = fopen("file.txt", "r"))== NULL) {
printf("\nERROR : Unable to open input file\n");
SetExitWithCode( 999 );
}else{
//code here
}
Can anyone help?
So, you want your array to look like this:
char data[25][35] //There is an extra 1 character per line to hold the null terminator character
Then simply read the whole file into that array
fread(data, 1, sizeof(data), infp);
And finally, replace the new line character in on each line with a terminator
for (int i = 0; i < 25; ++i) {
data[i][34] = 0;
}
This is the easiest solution to the problem, but it is also a bad way of doing it. It does not validate that the data is in the correct format, and everything is hard coded.