I'm trying to read the files in a directory and store each file name in an array of strings. I can't get it to work for the life of me. Here's the function:
char *readFile(char *dir){
char *fileStringArray[1000];
DIR *dirPointer;
int file_count = 0;
struct dirent *file;
struct stat fileType;
int i = 0;
if ((dirPointer = opendir(dir)) == NULL){
printf("Directory not found, try again\n");
return NULL;
}else{
printf("Reading files in directory\n");
while((file = readdir(dirPointer)) != NULL){ //iterate through contents of directory
stat(dir, &fileType);
if(i > 1){ //ignore . and .. directories that appear first
file_count++;
printf("%s\n", file->d_name);
strcpy(fileStringArray[i-2], file->d_name); //crashes, replace
//with [i] to not crash, but i-2 makes more sense to me
//fileStringArray[i-2] = &file->d_name; alternate idea
}
else{
i++;
}
}
int j;
for(j = 0; j < file_count; j++){
printf(":::%s\n", fileStringArray[j]); //print the string array
}
}
printf("Done reading\n\n");
closedir(dirPointer);
return dir;
}
There are two issues with your code. Main one is that you try to store your strings in 1000 element array of pointers to chars. Pointer to char is not enough to store string, it actually need to point to some memory. You can solve it on many ways, consider changing your strcpy function to strdup - which will allocate memory for you. Or you need to change your fileStringArray to be array of array's of chars (char fileStringArray[1000][100]).
Second issue is with that i , you should increment it unconditionally if you actually want to advance in your array.
Also, it would be nice if you could post full example, so I don't have to guess headers to include.
Related
i'm having a little big trouble in c. in particular im not able to save and modify a .txt file on an easy and efficient way.
the fact is: from a file.txt, i have to save all the words on a struct, and after that i will have to do some operations on this, like modify a specific word, a bubble sort, ecc ecc.
Im having problem on how to correctly save all the words in the struct, in the most generic possible way, even if a word from a line of the file is missing.
i mean:
1 line: word1 word2
2 line: word3
3 line: word4 word5
So even if a word is missing, i need to be able to save all this words, leaving something like a missing space in the struct.
the code that im posting is, at the moment, the best i can make with my hands, because i dont have any more ideas about what i should do.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX (10) //<- is 10 because the max numbers of letters in any single word is less than 10
struct word{
char word1[MAX+1]; //<- here im defying a struct with 2 char. this struct will contain the words coming out from the file.
char word2[MAX+1]; //<- max+1 because i have ti give 1 space for the " " or the "/n" case.
};
struct word *file_read(FILE *fp, int *count){
int dim = 2; //<- the int dim is the dimensione
char buf[1024]; //<- a simple buffer
struct word *w;
int conv = 0; //<- another counter that i will use in sscanf
int i;
if(!(w = calloc(dim , sizeof(*w)))){
free(w);
}
while(fgets(buf, sizeof(buf),fp)!= NULL){
conv = sscanf(buf, "%s %s", w->word1, w->word2);
if(conv >= 1){ //if conv doesnt increase, just no print
printf("\n%s ", w[*count].word1);
}
if(conv == 2){ //the same operation
printf("%s", w[*count].word2);
}
i++;
if(*count>= dim){
dim *= 2;
struct word* temp = realloc(w, sizeof(*w)*dim);
if(temp != NULL){
w = temp;
} else{
free(w);
return NULL;
}
(*count)++;
}
}
return w;
}
int main(int argc, char *argv[]){ //<- the file will be passed by argv[1] argument
FILE *fp; //<- im defying the FILE type
fp= fopen(argv[1], "r"); //<- im opening the file passed from argv[1], in reading mode
if(fp == 0){ //<- if file is not loaded, the programm have to stop.
printf("FILE IS NOT LOADED");
return 1;
}
struct word *w; //<- im creating a struct pointer called w
int count= 0;
if(!(w = file_read(fp, &count))){ //<- going to do the reading subroutine
return 0;
}
//AFTER THE READING, I SHOULD BE ABLE TO SAVE ALL THE WORDS IN THE STRUCT
//AND I SHOUL BE ABLE TO DO SOME OPERATIONS, LIKE VISUALIZE IT DIFFERENT WAYS
//DO BUBBLE SORT, QSORT, MODIFY THE WORDS IN THE STRUCT, ECC...
}
so, please, how can i make it works???? thank you everybody.
i hope i've been clear :)
user3386109's suggestion of adding int conv to the word structure is good. Still there are errors:
(*count)++ is out of place, so that it's never reached. Move it to the place of the pointless i++.
In order to not store every line's words in the first structure, change all w-> to w[*count]..
Okay! Pretty new to this stuff!
This is part of a bit bigger task and the problem I have now is that I have a list of names (100 names) inside a text file. They're written like this:
Sam (enter) Oliver (enter) Paul (enter) --- and so on.
So every name is on its own row. I'm trying to read this into a char array which I'll then print out to check if it works. I'll have to do something else to it afterward but I want to figure that out later.
Here's my code right now: (File names etc. are in Finnish so don't bother with that! :D)
#include <stdio.h>
int main() {
FILE *tiedosto;
char *array[100];
char nimi[] = "names.txt";
tiedosto = fopen(nimi, "r");
if (tiedosto == NULL) {
printf("Tiedostoa ei voida avata");
return;
}
int i;
for (i = 0; i < 100; i++) {
fscanf(tiedosto, "%s", &array[i]);
}
fclose(tiedosto);
printf("Tulostetaan taulukko \n");
// printf("%s \n",array);
for (i = 0; i < 100; i++) {
printf("%s \n", array[i]);
}
return 0;
}
You have got several errors in the code:
In this line:
fscanf(tiedosto, "%s", &array[i]);
You don't need to use an ampersand sign here. It's because the array is already the type of char*[] – in such situations, you must avoid passing char**.
In the following code segment:
if (tiedosto == NULL) {
printf("Tiedostoa ei voida avata");
return; // ***
}
The return type of the main() is an integer, so it must pass something non-void. Any non-zero return code would indicate an unsuccessful program closure.
In this declaration:
char *array[100];
The array is using a pointer alongside the array too. Thus this must be initialized using the malloc() function properly so that you don't hit with a segfault.
In case you don't want to get messed up of allocating memory, etc. try switching to two-dimensional array declaration:
char array[TOTAL_ENTRIES][PER_NAME_LEN];
I have described the 2-D array approach to avoid code complexity (read comments for explanation):
#include <stdio.h>
// Some global macros throughout this program
#define MAX_USERS 100
#define MAX_STRLEN 64
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
int main(void) {
const char *file_name = "names.txt";
FILE *fp = fopen(file_name, "r");
char name_list[MAX_USERS][MAX_STRLEN];
int count = 0;
// Using perror() is the best option here
if (fp == NULL) {
perror(file_name);
return EXIT_FAILURE;
}
// Reading the file contents and saving that into 2-D array
while (fscanf(fp, "%s", name_list[count++]) != EOF)
;
// Displaying the saved array contents
for (int i = 0; i < count - 1; i++)
fprintf(stdout, "%s\n", name_list[i]);
return 0;
}
In this program, the number of lines in the names.txt file can be anything lesser than or equal to 100.
I have an array (POINTS) with a length >20M of the following structure (point) and would like to save it in a binary file to read it afterwards in a different program:
typedef struct {
char *name;
unsigned char namelength;
} point;
if((POINTS = (point *) malloc (N * sizeof(point))) == NULL){
printf("when allocating memory for the points vector\n");
exit(0);
}
What I'm doing is the following; First I'm creating a variable namestot to know how many characters I have in total (some names may be empty):
for (i = 0; i < N; i++) namestot += POINTS[i].namelength;
Then I'm writing the array in a file:
if ((fin = fopen(name, "wb")) == NULL){
printf("the output binary data file cannot be open\n");
exit(0);
}
for ( i=0; i < N; i++){
if (POINTS[i].namelength){
if( fwrite(point[i].name, sizeof(char), POINTS[i].namelength, fin) != POINTS[i].namelength){
printf("when writing names to the output binary data file\n");
exit(0);
}
}
}
With that I create the file without issues. Now we change to another program with the binary file saved, so we open and read it:
if ((fin = fopen (argv[1], "r")) == NULL){
printf("the data file does not exist or cannot be opened\n");
exit(0);
}
//Here we allocate memory again for the POINTS vector
if((POINTS = (point *) malloc (N * sizeof(point))) == NULL){
printf("when allocating memory for the points vector\n");
exit(0);
}
if((allnames = (char *) malloc (namestot * sizeof(char))) == NULL){
printf("when allocating memory for the names vector");
exit(0);
}
if (fread(allnames, sizeof(char), namestot, fin) != namestot){
printf("when reading names from the binary data file\n");
exit(0);
}
//Setting pointers to names
for (i = 0; i < N; i++){
if(POINTS[i].namelength > 0){
POINTS[i].name = allnames;
allnames += POINTS[i].namelength;
}
}
However, when I try to read the first non-empty name the program prints the entire array of names, any advice on how to set the pointers to the mesan to have the POINTS array as I had it in the first program?
Thanks!
PS: if there's any non-declared variable I've probably forgot to paste it here, that's not the issue.
You are writing variable length strings to files, so when you read it you need to know length of individual string
You may decide to include length string along with the string to write in the file or ensure you write trailing '\0' to indicate earlier string ends and new one begins from next byte, your reader program will have to parse the strings accordngly
prints the entire array of names
Sounds like because you do not tell your program the end of each name, print char * stop when meet a \0 .
I need to write a code that will print the frequency of each word from a given file. Words like "the" and "The" will count as two different words. I've written some code so far but the command prompt stops working when I try to run the program. I just need some guidance and to be pointed in the best direction for this code, or I would like to be told that this code needs to be abandoned. I'm not very good at this so any help would be very appreciated.
#include <stdio.h>
#include <string.h>
#define FILE_NAME "input.txt"
struct word {
char wordy[2000];
int frequency;
} words;
int word_freq(const char *text, struct word words[]);
int main (void)
{
char *text;
FILE *fp = fopen(FILE_NAME, "r");
fread(text, sizeof(text[0]), sizeof(text) / sizeof(text[0]), fp);
struct word words[2000];
int nword;
int i;
nword = word_freq(text, words);
puts("\nWord frequency:");
for(i = 0; i < nword; i++)
printf(" %s: %d\n", words[i].wordy, words[i].frequency);
return 0;
}
int word_freq(const char *text, struct word words[])
{
char punctuation[] =" .,;:!?'\"";
char *tempstr;
char *pword;
int nword;
int i;
nword = 0;
strcpy(tempstr, text);
while (pword != NULL) {
for(i = 0; i < nword; i++) {
if (strcmp(pword, words[i].wordy) == 0)
break;
}
if (i < nword)
words[i].frequency++;
else {
strcpy(words[nword].wordy, pword);
words[nword].frequency= 1;
nword++;
}
pword = strtok(NULL, punctuation);
}
return nword;
}
First off all:
char *text;
FILE *fp = fopen(FILE_NAME, "r");
fread(text, sizeof(text[0]), sizeof(text) / sizeof(text[0]), fp);
Reads probably 4 bytes of your file because sizeof(text[0]) is 1 and sizeof(text) is probably 4 (depending on pointer size). You need to use ftell() or some other means to get the actual size of your data file in order to read it all into memory.
Next, you are storing this information into a pointer that has no memory allocated to it. text needs to be malloc'd or made to hold memory in some way. This is probably what is causing your program to fail to work, just to start.
There are so so SO many further issues that it will take time to explain them:
How you are using strcpy to blow up memory when you place it intotempstr
How even if that weren't the case, it would copy probably the whole file at once, unless the file had NULL terminated strings within, which it may, so perhaps this is ok.
How you compare nwords[i].wordy, even though it is not initialized and therefore garbage.
How, even if your file were read into memory correctly, you look a pword, which is unitialized for your loop counter.
Please, get some help or ask your teacher about this because this code is seriously broken.
I was wondering how to properly read a file and place each line in a string of arrays in C.
I have a file with the following written on it
one
two
three
four
I tried writing something like this:
int read_file(FILE *fp){
char readLine[MAX_LEN];
char *myarray[20];
int counter =0;
int i =0;
while(fgets(readLine,MAX_LEN,fp) != NULL){
myarray[counter] = readLine;
counter++;
}
/*printing the array*/
while(i<counter){
printf("%d %s",i,myarray[i]);
i++;
}
}
and the main would be something like
int main(){
FILE *fp;
fp = fopen("my.txt","r");
if(fp == NULL){
fprintf(stderr,"File does not exist");
return EXIT_FAILURE;
}
read_file(fp);
}
however, when printing I get:
four
four
four
four
even when I print using printf("%s",myarr[2]) , I still get four
Anyone knows what the problem may be?
You really need to make a copy of the line (by way of strdup()) as you are overwriting the buffer used to accept the input:
int read_file(FILE *fp){
char readLine[MAX_LEN];
char *myarray[20]; // Note char pointer!
int i, counter = 0;
while (counter < 20 && fgets(readLine,MAX_LEN,fp) != NULL) { // Note limit!
myarray[counter] = strdup(readLine);
counter++;
}
/*printing the array*/
for (i = 0; i < counter; i++)
printf("%d %s",i,myarray[i]);
/* free the lines */
for (i = 0; i < counter; i++)
free(myarray[i]);
}
myarray[counter] = readLine;
is the problem. You are overriding the read line pointer values each time.
use strcpy to copy the buffer content instead.
In addition as commented: you are not declaring array of strings, merely one string.
Change it to:
char myarray[4][20];
Of course, 4 is an example. Change it to any number of lines or use dynamic allocation.