I try to read a file from this code. I am trying to load images and store them into my program as strings, so I can later create the identical image with fprintf to a new file. I am not allowed to use some file duplication; I need to load the files in as a string and write them to a new file later. What I am attempting is to have a char array, and since one char is one byte the array is as long as the file size, and each element of the char array corresponds to one byte of the diamond block texture, and I want to also be able to write this string from the code to a new file, and have another diamond block that I can open with an image viewer.
#include <stdio.h>
#include <stdlib.h>
char Contents[468];
int main(int argc, char *argv[]) {
char *WD = getenv("HOME");
char Path[strlen(WD)+strlen("/Desktop/diamond_block.png")+1];
sprintf(Path, "%s/Desktop/diamond_block.png", WD);
FILE *File = fopen(Path, "r");
fscanf(File, "%s", Contents);
printf(Contents);
}
The result is just four letters, âPNG, and it is supposed to be hundreds of characters meaning the file is NOT being fully read. I suspect it is somehow being terminated early by some terminating character, but how can I solve my problem?
This is a very basic answer to your question. With the code below you may understand what's your issue. This code need a good review to intercept all the errors the used functions may return. By the way ... enjoy it!
The code loads the whole file fname into the char array imgMem. It compute the file dimension on the variable n, allocates the memory for the array imgMem (malloc) and then loads the whole file into imgMem (fread).
Then the code writes the first 30 bytes of the file in two format:
the hex value of the byte
the char value if the byte has a console representation (otherwise prints a .)
Here the code:
#include <unistd.h>
#include <stdio.h>
#include <malloc.h>
int main(void)
{
const char * fname = "/home/sergio/Pictures/vpn.png";
FILE * fptr;
char * imgMem=NULL;
long n;
int i;
fptr=fopen(fname, "r");
//Determine the file dimension
fseek(fptr,0,SEEK_END); n=ftell(fptr);
//Set the file cursor to the beginning
fseek(fptr,0,SEEK_SET);
printf("The file is %lu byte long.\n\n",n);
//Allocate n bytes to load the file
imgMem = malloc((size_t)n);
//Load the file
fread(imgMem,(size_t)n,1,fptr);;
for(i=0; i<30; i++) {
printf("[%02X %c] ",
(unsigned char)imgMem[i],
(imgMem[i]>31 && imgMem[i]<127)?
imgMem[i]:'.'
);
if ((i+1)%8==0)
puts("");
}
puts("");
free(imgMem);
fclose(fptr);
return 0;
}
Related
I'm trying to copy contents of one file into another. Before I finished, I wanted to print the contents out on screen to see that things are working. But they didn't.
I included...
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
and my code is...
void decodeBin(char * filename){
//opens filename for reading and outfilename for writing
FILE * input = fopen(filename, "r");
char file_name[] = "";
strcpy(file_name, filename);
char out_file[] = "out";
strcat(out_file, file_name);
FILE * output = fopen(out_file, "w");
char ch;
if (input != NULL){
while((ch = fgetc(input)) != EOF)
printf("%c", ch);
}
fclose(input);
fclose(output);
}
I looked at the other stack overflow posts, which suggested to check if file pointer is not null, which I do. What's going wrong?
You're causing undefined behavior by writing outside the bounds of the file_name and out_file arrays. When you don't specify a size for the array, the size is determined from the string you use to initialize it. So it's equivalent to
char file_name[1] = "";
char out_file[4] = "out";
The extra byte is for the trailing null.
Since you didn't declare the arrays big enough for the strings you're copying into them, you get undefined behavior.
You need to declare the size of the arrays big enough to hold the largest possible filename. Or use malloc() to size it in terms of the parameters.
There's no need for the file_name variable, since it's just a copy of filename, and you can use that directly.
char *outfile = malloc(strlen(filename) + sizeof("out"));
sprintf(outfile, "out%s", filename);
Then at the end of the function, do
free(outfile);
I'm trying to read a file "data.txt" with a single line "00:612:33188" (each number represents a field of data, "changes:size:permission"), and write that information into a struct. I want to write the code in general for any number of characters in those fields.
My question is regarding the use of fscanf. I cannot seem to make it work. The following code produces a segmentation fault error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXHITS 50
#define FIELDMAX 100
#define TOTALELEMENTS 100000
typedef struct Elements{
char changes[FIELDMAX];
char size[FIELDMAX];
char permission[FIELDMAX];
} Elements;
int main(int argc, char const *argv[]) {
if(argc < 2) {
printf("\nSyntax: fscanf data\n\n");
exit(EXIT_FAILURE);
}
Elements total[TOTALELEMENTS];
Elements hits[MAXHITS];
int total_elements = 0;
int total_hits = 0;
FILE *fp;
// open the file and scan each field copying to the corresponding struct
fp = fopen (argv[1], "r");
if (fp){
fscanf(fp,"%99s:%99s:%99s", total[total_elements].changes,
total[total_elements].size, total[total_elements].permission);
printf("%s\n%s\n%s\n", total[total_elements].changes,
total[total_elements].size, total[total_elements].permission);
fclose (fp);
}
return 0;
}
The "%s" format reads space delimited strings. If there's no space, it will greedily read as much as it could.
In your case it means that the whole line will be in the changes field, leaving the remaining members uninitialized.
For non-space delimited records you could read the whole line into a string, and then tokenize on the separator.
The likely culprit of the segfault is the huge local variable total
#define MAXHITS 50
#define FIELDMAX 100
#define TOTALELEMENTS 100000
typedef struct Elements{
char changes[FIELDMAX];
char size[FIELDMAX];
char permission[FIELDMAX];
} Elements;
int main () {
...
Elements total[TOTALELEMENTS];
}
100000 * 300 bytes. You get call stack overflow.
If you reduce the TOTALELEMENTS to, say, 100, your code works file with my test.
I have a binary file which contains 3 differents structs and a christmas text. On the first line of the binaryfile have they provided me with a int which represents the size of a package inside the file. A package contains 3 structs ,the chistmastext and the size.
The structs lies in a file called framehdr.h and the binary file I'm reading is called TCPdump.
Now am I trying to create a program att will read each package at a time and then withdraw the text.
I have started with something like this:
#pragma warning(disable: 4996)
#include <stdio.h>
#include <stdlib.h>
#include "framehdr.h"
#include <crtdbg.h>
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
FILE *fileOpen;
char *buffer;
size_t dataInFile;
long filesize;
// The three structs
struct ethernet_hdr ethHdr;
struct ip_hdr ipHdr;
struct tcp_hdr tcpHDr;
fileOpen = fopen("C:\\Users\\Viktor\\source\\repos\\Laboration_3\\Laboration_3\\TCPdump", "rb");
if (fileOpen == NULL)
{
printf("Error\n");
}
else
{
printf("Success\n");
}
char lenOf[10];
size_t nr;
// Reads until \n comes
fgets(lenOf, sizeof(lenOf), fileOpen);
sscanf(lenOf, "%d", &nr);
// Withdraw the size of a package and check if it's correct
printf("Value: %d\n", nr);
printf("Adress: %d\n", &nr);
void *ptr;
fread(&ptr, nr, 1, fileOpen);
int resEth = 14;
printf("resEth: %d\n", resEth);
int resIP = IP_HL((struct ip_hdr*)ptr);
printf("ResIP: %d\n", resIP);
int resTcp = TH_OFF((struct tcp_hdr*)ptr);
printf("tcpIP: %d\n", resTcp);
int res = resEth + resIP + resTcp;
printf("Total: %d", res);
fclose(fileOpen);
//free(buffer);
system("pause");
return 0;
}
I know that the first struct ethernet will always have the size of 14 but I need to get the size of the other 2 and I'm suppose to use IP_HL and TH_OFF for that.
But my problems lies in that I can't seem to read the entire package to one
void * with the fread. I get noting in my *ptr.
Which in turn makes the code break when I try to convert the void * to one of the structs ones.
What I'm doing wrong with the void *?
Two problems:
First you should not really use text functions when reading binary files. Binary files doesn't really have "lines" in the sense that text file have it.
Secondly, with
void *ptr;
fread(&ptr, nr, 1, fileOpen);
you are passing a pointer to the pointer variable, you don't actually read anything into memory and then make ptr point to that memory. What happens now is that the fread function will read nr bytes from the file, and then write it to the memory pointed to by &ptr, which will lead to undefined behavior if nr > sizeof ptr (as then the data will be written out of bounds).
You have to allocate nr bytes of memory, and then pass a pointer to the first element of that:
char data[nr];
fread(data, nr, 1, fileOpen);
You should also get into the habit of checking for errors. What if the fread function fails? Or the file is truncated and there isn't nr bytes left to read?
You can check for these conditions by checking what fread returns.
And not only check for fread, there are more functions than fopen that can fail.
I am currently trying to implement a program that intakes a file, reads the file and copies its contents to an array (farray). After this we copy the contents of farray as strings separated by null terminators into a string array called sarray.
For example, say farray contains "ua\0\0Z3q\066\0", then sarray[0] should contain "ua", sarray[1] should contain "\0", sarray[2] should contain "Z3q", and finally sarray[3] should contain "66"
However I cannot figure out how to separate the string by the null terminators. I currently can only use the system calls like fread, fopen, fclose, fwrite...etc. Can someone please help me?
src code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char *argv[]){
char *farray;
const char *sarray;
long length;
int i;
//Open the input file
FILE *input = fopen(argv[1], "rb");
if(!input){
perror("INPUT FILE ERROR");
exit(EXIT_FAILURE);
}
//Find the length
fseek(input, 0, SEEK_END);
length = ftell(input);
fseek(input, 0, SEEK_SET);
//Allocate memory for farray and sarray
farray = malloc(length + 1);
//Read the file contents to farray then close the file
fread(farray, 1, length, input);
fclose(input);
//Do string splitting here
//Free the memory
free(farray);
return 0;
}
Keep the number of characters length for further use.
What characters do you want to replace by the null characters? Based on that, walk through farray, replace the appropriate characters by the null character. While doing that, count the number of characters that were replaced by the null characters.
If the number of characters that were replaced by the null character is N, then the array of pointers needs to be of size N+1.
Allocate memory for the array of pointers.
Walk through farray again and make sure the elements in the array of pointers point to the right location in farray.
Update, in response to OP's comment
In step (2) above, don't replace anything, just compute N.
In step (5), use strdup and assign the returned value to the elements of the array of pointers instead pointing to farray.
For my assignment, I have to read in a text file with a varying amount of lines. They follow the following format:
AACTGGTGCAGATACTGTTGA
3
AACTGGTGCAGATACTGCAGA
CAGTTTAGAG
CATCATCATCATCATCATCAT
The first line is the original line I will testing the following ones against, with the second line giving the number of remaining lines.
I'm having trouble trying to save these to a struct, and can't even get the first line to save. I tried using the void function with an array and it seems to work, but can't seem to transfer it over to structs.
Here's my code so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 25
struct dna {
char code[LENGTH];
};
int main(){
char filename[] = "input1.txt";
FILE *input = fopen("input1.txt","r");
char firstDna[LENGTH]="";
struct dna first;
struct dna first.code[]= "";
makeArray(input,first);
// printf("%s",filename);
system("pause");
return 0;
}
void makeArray(FILE *input,struct dna first){
int i=-1;
//nested for loops to initialze array
//from file
while(i != '\n'){
fscanf(input,"%c",first[i].code);
printf("%c", first[i].code);
i++;
}//closing file
fclose(input);
}
Since this is for a class assignment, I want to preface this by saying that a good way to tackle these types of assignments is to break it up into tasks, then implement them one by one and finally connect them. In this case the tasks might be something like:
parse the first line into a (struct containing a) char array.
parse the number into an int variable
parse each remaining line in the file like you did with the first line
test the first line against the other lines in the file (except the number)
You also mentioned in a comment that the struct is for extra credit. For that reason, I'd recommend implementing it using just a char array first, then refactoring it into a struct once you have the basic version working. That way you have something to fall back on just in case. This way of developing might seem unnecessary at this point, but for larger more complicated projects it becomes a lot more important, so it's a really good habit to get into as early as possible.
Now, let's look at the code. I'm not going to give you the program here, but I'm going to identify the issues I see in it.
Let's start with the main method:
char filename[] = "input1.txt";
FILE *input = fopen("input1.txt","r");
This opens the file you're reading from. You're opening it correctly, but the first line is in this case unnecessary, since you never actually use the filename variable anywhere.
You also correctly close the file at the end of the makeArray function with the line:
fclose(input);
Which works. It would, however, probably be better style if you put this in the main method after calling the makeArray function. It's always a good idea to open and close files in the same function if possible, since this means you will always know you didn't forget to close the file without having to look through your entire program. Again, not really an issue in a small project, but a good habit to get into. Another solution would be to put the fopen and fclose functions in the makeArray function, so main doesn't have to know about them, then just send the char array containing the filepath to makeArray instead of the FILE*.
The next issue I see is with how you are passing the parameters to the makeArray function. To start off, instead of having a separate function, try putting everything in the main method. Using functions is good practice, but do this just to get something working.
Once that's done, something you need to be aware of is that if you're passing or returning arrays or pointers to/from functions, you will need to look up the malloc and free functions, which you may not have covered yet. This can be one of the more complex parts of C, so you might want to save this for last.
Some other things. I won't go into detail about these but try to get the concepts and not just copy paste:
struct dna first.code[]= ""; should probably be first.code[0] = \0;. \0 is used in C to terminate strings, so this will make the string empty.
Passing %c to fscanf reads a single character (you can also use fgetc for this). In this case, it will probably be easier using %s, which will return a word as a string.
Assuming you do use %s, which you probably should, you will need to call it twice before the loop - once to get the first DNA sequence and another time to get the number of other DNA sequences (the number of iterations).
Each iteration of the loop will then test the original DNA sequence against the next DNA sequence in the file.
I hope that helps!
sample to fix
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 25
struct dna {
char code[LENGTH];
};
struct dna *makeArray(FILE *input, int *n);//n : output, number of elements
int main(void){
char filename[] = "input1.txt";
FILE *input = fopen(filename,"r");
struct dna first = { "" };
fscanf(input, "%24s", first.code);//read first line
printf("1st : %s\n", first.code);
int i, size;
struct dna *data = makeArray(input, &size);//this does close file
for(i = 0; i < size; ++i){
printf("%3d : %s\n", i+1, data[i].code);
}
free(data);//release data
system("pause");
return 0;
}
struct dna *makeArray(FILE *input, int *n){//n : output, number of elements
int i;
fscanf(input, "%d", n);//read "number of remaining lines"
struct dna *arr = calloc(*n, sizeof(struct dna));//like as struct dna arr[n] = {{0}};
for(i = 0; i < *n; ++i){
fscanf(input, "%24s", arr[i].code);
}
fclose(input);
return arr;
}
a simple fix might be :
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 25
struct dna {
char code[LENGTH];
};
void makeArray(FILE *input,struct dna *first){
int i=0;
fscanf(input,"%c",&first->code[i]);
printf("%c",first->code[i]);
while(first->code[i] != '\n' && i < LENGTH){
i++;
fscanf(input,"%c",&first->code[i]);
printf("%c",first->code[i]);
}
}
int main() {
struct dna first;
char filename[] = "input1.txt";
FILE *input = fopen(filename,"r");
makeArray(input,&first);
fclose(input);
printf("%s",first.code);
return 0;
}
PS: i tried to not change your original code
in order to change the code[Length] in the makeArray function you will have to pass it's adresse this is why i call mkaeArray function this way : makeArray(input,&first);.