game of life in C, how to write in file? - c

So i have implemented the game of life and now have to put every new generated field into a gif or pbm and at the end with a command I create an animated gif.
The below function is given but I don't get the first parameter, a pointer const char? I see in the function that is the filename, but how do I write that, I'm really confused.
static int write_pbm_file(const char *fn, struct game_field *gf) {
int i, j;
FILE *fp;
fp = fopen(fn, "w+");
if(!fp){
printf("unable to open '%s' - '%s'\n", fn, strerror(errno));
return -1;
}
fprintf(fp, "P1\n");
fprintf(fp, "%c\n", gf->length);
fprintf(fp, "%c\n", gf->length);
for(i = 0; i < gf->length; i++)
for(j = 0; j < gf->length; j++)
fprintf(fp, "%c\n", gf->field[i][j] == 0 ? 48 :
gf->field[i][j] == 1 ? 219 : 197);
fclose(fp);
return 0;
}
That's the code where I get to the above function:
while( iterations > 0 ) {
write_pbm_file(..., pstField);
pstField = game_iteration(pstField);
iterations--;
}
What should I write to create this files? Please help
Thank you!

A pointer to non-changing character data can most easily be produced by just using a string literal:
write_pbm_file("life.pbm", pstField);
You probably want to change the filename for each iteration, though. Maybe something like this:
char filename[100];
while(...)
{
sprintf(filename, "life-%03d.pbm", iteration);
write_pbm_file(filename, pstField);
This re-uses your iteration counter (which counts backwards), so the first file to be written will have the largest number. I added 0-padding to three decimal digits, of course I don't know how many iterations you need.

The parameter fn is simply a path to a file. On a unix system you might write "/home/someuser/somefile.ext", on windows you'd write "C:\\Some\\Path\\somefile.ext"
You could also make it configurable through the program arguments, using argv[1] or the like. E.g:
int main(int argc, char** argv) {
if (argc < 1) exit(1);
char* filename = argv[1];
...
while( iterations > 0 ) {
write_pbm_file(filename, pstField);
pstField = game_iteration(pstField);
iterations--;
}
}

Assuming you have a game_field field, writing it out to, say, /home/you/foo.pbm would be
write_pbm_file("/home/you/foo.pbm", &field);
const char * is a type that string literals, char *, const char [] and char [] decay to.

Related

How to read text from a file into an array and then print the whole array out

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.

Reading text file into an array in C

I want to parse a .txt file into a 1D array in C. I'm using the fgets function to read the contents of the file into the array("waveform" as the array into which the file contents are to be stored - defined as a "char"). The saved values need to be saved into a new array as integer values. I am not sure where I am going wrong.
P.S: I am new to programming in C, please bear with me :)
Please ignore the indexing issues, done due to pasting
int main(){
int a, win[10];
FILE *filename = fopen("testFile.txt","r");
char waveform[10];
if (filename == NULL)
{
printf("Error opening file.\n");
exit(8);
}
for(int i =0;1;i++){
if(fgets(waveform[i], 10, filename) == NULL);
break;
if(i < 10)
{
a = atoi(waveform[i]);
win[i] = a;
}
}
fclose(filename);
return 0;
}
Compiler errors - image embedded
Data in testFile.txt:
1 to 10 in a row vector.
You are on the right track. Here is my contribution on the topic:
Open the file (fopen)
Count number of lines (getc and rewind)
Read all lines into array (getline)
Free memory and close file (free and fclose)
Code example:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
// Open File
const char fname[] = "testFile.txt";
FILE *fp = fopen(fname, "r");
if( !fp )
goto error_open_file;
printf("Opened file: %s\n", fname);
// Count Lines
char cr;
size_t lines = 0;
while( cr != EOF ) {
if ( cr == '\n' ) {
lines++;
}
cr = getc(fp);
}
printf("Number of lines: %ld\n", lines);
rewind(fp);
// Read data
{// 'goto' + data[lines] causes error, introduce block as a workaround
char *data[lines];
size_t n;
for (size_t i = 0; i < lines; i++) {
data[i] = NULL;
size_t n = 0;
getline(&data[i], &n, fp);
if ( ferror( fp ) )
goto error_read_file;
}
for (size_t i = 0; i < lines; i++) {
printf("%s", data[i]);
free(data[i]);
}
}
// Close File
fclose(fp);
return 0;
error_read_file:
perror("fopen ");
return 1;
error_open_file:
perror("getline ");
return 2;
}
There are several errors in this loop
for(int i =0;1;i++){
if(fgets(waveform[i], 10, filename) == NULL);
break;
if(i < 10)
{
a = atoi(waveform[i]);
win[i] = a;
}
}
For starters there is a semicolon after the if statement
if(fgets(waveform[i], 10, filename) == NULL);
^^^
Secondly the fgets call
fgets(waveform[i], 10, filename)
^^^
is invalid because the type of the expression waveform[i] is char.
And correspondingly this statement
a = atoi(waveform[i]);
is also invalid.
There must be at least
fgets( waveform, 10, filename)
and
a = atoi( waveform );
I suppose that each line of the file contains exactly one number. (Otherwise you should use for example sscanf to extract numbers from a line using an internal additional loop.)
The loop can look like
int i = 0;
for ( ; i < 10 && fgets( waveform, 10, filename) != NULL; i++ )
{
a = atoi( waveform );
win[i] = a;
}
After the loop the variable i will contain the actual number of elements of the array win.
Pay attention to that the name filename is not good for a pointer of the type FILE *. File name is the string "testFile.txt" in your code.
If you want to use the fgets() function you don't have to put it into a loop. Indeed, the second argument of fgets() is the number of elements you want to read.
I would have put the fgets() into a singl-line instruction, and then loop from 0 to 10 to make the conversion from char to int with the atoi() function.
Moreover, you have a ; at the end of your if() statement, so you'll execute it not in the way you want.

Print out first line of input file char by char, but nothing comes to screen

So Im trying to print out the first line of a file thats being passed in lets say its a plain text file with a couple of words in the first line.
I open the file and pass it through a function that does some work on the file called process. This little bit of work if for debugging reason , because my ultimate goal is to read in the entire text file line my line and process each line and reverse the words in that line.
But im stuck here i run the program with a text file argument and i get nothing in return and i know my logic sounds right i think? I just want this to ultimately printout every character in that line. Then eventually put all those characters in a char array or char instream[500]
Can someone tell me what iam doing wrong?
#include <stdio.h>
#include <stdlib.h>
void process(FILE *infile);
int main(int argc, char *argv[])
{
int i;
FILE *fp;
printf("argc = %d\n",argc);
for(i = 1 ; i <= argc; i++)
{
fp = fopen(argv[i], "r");
if(fp == NULL)
{
printf("The file: %s doesnt exist.\n", argv[i]);
}
else
{
printf("The file: %s does exist \n",argv[i]);
process(fp);
}
}
return 0;
}
void process(FILE *infile)
{
int k =0;
char iochar;
char instream[500];
while((iochar = getc(infile)) != '\n')
{
printf("Hi there %c", iochar ); // nothing prints out here why not??
//instream[k++] = iochar;
}
}

Create new files, whose name depends on a variable from the program

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;
}

output to a file using command line

I am writing a program that should be able to take command line parameters.
Basically, the user must be able to specify a file name through command prompt while calling the program. i.e the program should be able to take in a parameter like:
doCalculation -myOutputfile.txt. where doCalculation is the name of my program and myOutputfile is the file I want my results written to (i.e output the results of my calculations to the specified file name).
So far I can call my function through the command prompt. I am not sure how to get my program to write to the filename specified (or create this file if it does not exist already).
My code is as follows:
int main(int argc, char *argv[])
{
FILE* outputFile;
char filename;
// this is to make sure the code works
int i = 0;
for (i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
//open the specified file
filename= argv[i];
outputFile = fopen("filename", "r");
//write to file
fclose(outputFile);
}
So a couple things I noticed...
If you want to write to the file, use "w" for write-mode instead of "r" for read-mode when opening the file.
You declared filename as a single character rather than a pointer to a string (char *). Making it a pointer will allow filenames with a length > 1 (array of chars rather than a single char).
As Ashwin Mukhija mentioned, you're using i after the for loop set it to 2, when infact you want the 2nd (index 1) argument.
You had the filename argument in the open() function as a literal "filename" rather than your filename variable.
See if this code helps solve your problem, (I also tossed a fprintf() in there to show you how you can write to the file).
Cheers!
int main(int argc, char *argv[])
{
FILE* outputFile;
char* filename;
// this is to make sure the code works
int i = 0;
for (i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
//saftey check
if(argv[1])
{
filename = argv[1];
//open the specified file
outputFile = fopen(filename, "w");
fprintf(outputFile, "blah blah");
//write to file
fclose(outputFile );
}
return 0;
}

Resources