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