I'm trying to write a program that will save "X" number of simple textfiles- however, X is determined by the user once the program has run. I can't seem to find any help on the net as to how to solve the following two things, so any tips will be massively appreciated!
1) How do I declare these textfiles at the start of the program if I don't know how many there will be?
So far, I'm used to using:
FILE* outfile;
But what I really need is:
FILE* outfile_0, outfile_1, outfile_2... outfile_X;
The solution that comes to mind looks like a loop, but I know that this won't work!
for (i=0;I<X;i++){
FILE* outfile_i // obviously, this just literally calls it "outfile_i"
}
2) How do I name them?
I want to call them simple names, such as "textfile_1, textfile_2" etc, but I don't see how that would be possible using:
outfile=fopen("C:\\textfile.txt","w");
Again, I thought perhaps making a loop (?!) but I know that this won't work:
for(i=0;i<X;i++){
outfile_i=fopen("C:\\textfile_i.txt","w");
}
There's absolutely no way of knowing what variable "X" is before running the program.
EDIT: Problem solved- I wasn't aware you could create arrays of "FILE*", thanks for all the help!
Something like this should work, but requires error handling and close/free operations.
FILE **outfile = malloc(sizeof(FILE*) * X);
for(i=0;i<X;i++){
char buffer[1024];
sprintf(buffer, "%s_%d.txt", "textfile", i);
outfile[i] = fopen(buffer, "w");
}
You have to put all your FILE * variables in an array. I would do:
char filename[80];
char number[10];
/* Allocate our array */
FILE ** files = malloc((sizeof(FILE *) * X) + 1); /* We allocate a size of X+1 because we'll have X elements + a last NULL element. */
/* Populate our array */
for (int i = 0; i < X; i++)
{
strcpy(filename,"C:\\textfile_");
itoa(i, number, 10); /* Here 10 means we use decimal base to convert the integral value. */
strcat(filename, number);
strcat(filename, ".txt");
files[i] = fopen(filename, "w");
}
files[i] = NULL; /* Here we set the last element of our array to NULL (so when we iterate over it we can stop when we encounter NULL). */
Then you can access all your files like this:
for (int i = 0; files[i] != NULL; i++)
{
FILE * current = files[i];
/* Do something with "current" here. */
}
PS: Some security checks are required:
malloc → Verify it doesn't return NULL.
itoa → Verify that output string is valid.
fopen → Verify that the file was opened.
you have to store your variables in some structure (an array, a list ...) and to create some strings in memory. For example :
#include <stdio.h>
#define X 5
int main() {
FILE* outfiles[X];
unsigned short i;
char fn[32];
for (i = 0; i < X; ++i) {
sprintf(fn, "outfile_%u", i);
outfiles[i] = fopen(fn, "w");
}
}
Try this-
char buffer[100];
FILE* outfile[X];
for(i=0;i<X;i++){
snprintf(buffer,100,"C:\\textfile_%d.txt",i);
outfile[X]=fopen(buffer,"w");
}
This should help you.
# include <stdio.h>
# include <string.h>
int main ()
{
char *textfile;
int i, X;
textfile = (char *) malloc (128 * sizeof (char));
FILE *fptr;
printf ("Enter the value of X: ");
scanf ("%d", &X);
for (i=1 ; i<=X ; i++)
{
sprintf(textfile, "textfile_%d.txt", i);
fptr = fopen (textfile, "w");
fclose (fptr);
}
return 0;
}
Related
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.
Absolutely new to C. I am trying to write a program to either read integers contained in a file (passed as arg) or from stdin. First number read is supposed to indicate the array size.
I have something but it throws segmentation fault. Please help.
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* argv[]) {
FILE *f;
int n, numbers[n], firstNum;
if (argc != 0)
{
f = fopen(argv[1], "r");
fscanf(f, "%d", & firstNum);
int numbersArray[firstNum];
for (int i = 0; i < firstNum; i++)
{
fscanf(f, "%d", &numbersArray[i]);
}
for (int i = firstNum; 0 <= i; i--)
{
printf("Numbers: %d\n\n", numbersArray[i]);
}
fclose(f);
}
else
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
fscanf(stdin, "%d", &numbers[i]);
printf("%d\n", i, numbers[i]);
}
return 0;
}
First off always initialize your variables like kaylum and myself mentioned in the comments.
Unlike some other programming languages C doesn't initialize your variables for you.
Now for the question you posted, you got the idea mostly correct but there are things that i suggest you change:
int n, numbers[n], firstNum;
to
int n = 0, numbers[1000], firstNum = 0;
If you're not happy with that you could move the numbers[n] lower when n is initialized but i wouldn't advise that.
Instead of that, since you're learning C have a look at dynamically allocated arrays using pointers.
Some links to help you understand pointers:
https://www.cprogramming.com/tutorial/c/lesson6.html
https://www.tutorialspoint.com/cprogramming/c_pointers.htm
Next have a look at your fopen it has a return value that tells you if it succeeded to open the file you requested.
So you can add:
f = fopen(argv[1], "r");
if (f == NULL)
{
printf("File Not Found!");
return -1;
}
Modify the condition to suite the way you want to handle that error.
When you're reading the file the user specifies the size of the array you're reading but you should consider the fact that the file may not contain the exact amount of elements.
The function that you are using fscanf has a way to tell you that and that's it's return value.
It will return EOF which is a special value that translates to End Of File.
Consider modifying your fscanf to this:
if (fscanf(f, "%d", &firstNum) == EOF)
{
printf("ERROR");
}
Or if you're in a for loop put break
The last thing is that you don't have to explicitly use fscanf for stdin, the user has specified that he will input it through stdin so you can just as well use scanf.
Hope this helps and good luck with your future C endeavors.
FILE *pFile;
pFile = fopen("address01", "r");
int yup[8];
int* array[7];
for (int i = 0;i < 7; i++) {
while (!feof(pFile)) {
fgets(yup, 8, pFile);
puts(yup); //It DOES print each line
array[i] = yup;
}
}
fclose(pFile);
printf("First: %d",array[0]); //I want it to print the first thing in the file, but I get a
//crazy number. It should be 10.
printf("Second: %d",array[1]); //I want it to print the 2nd thing in the file, but I get a
//crazy number. It should be 20
//etc.
Essentially, I want to be able to select any number in my array for later manipulation.
Contents of address01:
10
20
22
18
E10
210
12
The prototype of fgets is
char * fgets ( char * str, int num, FILE * stream );
You are using an int* (int yup[8]) where you should be using a char *.
If the address01 file you are reading is text, then you need to change your definition of yup. If your file is binary you need to provide information on what the format of your binary is.
The array you have defined is a pointer to an int array, but you need an array of char *. The other problem is that your yup variable is always pointing to the same address, so you are just overwriting the same memory. You need to allocation (malloc()) your yup variable before each fgets in order for each read to be placed in new memory.
Something like this:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *pFile;
pFile = fopen("address01", "r");
char *yup;
char *array[7];
for (int i = 0;i < 7; i++) {
yup = (char *) malloc(8);
if (yup == NULL) {
// this indicates you are out of memory and you need to do something
// like exit the program, or free memory
printf("out of memory\n");
return 4; // assuming this is running from main(), so this just exits with a return code of 4
}
if (feof(pFile)) {
break; // we are at the end, nothing left to read
}
fgets(yup, 8, pFile);
puts(yup);
array[i] = yup;
}
fclose(pFile);
}
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.