I try to calculate the checksum of the file in c.
I have a file of around 100MB random and I want to calculate the checksum.
I try this code from here: https://stackoverflow.com/a/3464166/14888108
int CheckSumCalc(char * filename){
FILE *fp = fopen(filename,"rb");
unsigned char checksum = 0;
while (!feof(fp) && !ferror(fp)) {
checksum ^= fgetc(fp);
}
fclose(fp);
return checksum;
}
but I got a Segmentation fault. in this line "while (!feof(fp) && !ferror(fp))"
Any help will be appreciated.
The issue here is that you are not checking for the return value of fopen. fopen returns NULL if the file cannot be opened. This means that fp is an invalid pointer, causing the segmentation fault.
You should change the code to check for the return value of fopen and handle the error accordingly.
int CheckSumCalc(char * filename){
FILE *fp = fopen(filename,"rb");
if(fp == NULL)
{
//handle error here
return -1;
}
unsigned char checksum = 0;
while (!feof(fp) && !ferror(fp)) {
checksum ^= fgetc(fp);
}
fclose(fp);
return checksum;
}
Related
I am trying to make a program in C, that reads a text file and replace \n with \r\n to the same file converting the line ending from UNIX to DOS. I use another code in stackoverflow that convert DOS to UNIX and treat the file as a binary file. my problem is converting to UNIX to DOS. Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
// Return a negative number on failure and 0 on success.
int main()
{
const char* filename = "textfile.txt";
// Get the file size. We assume the filesize is not bigger than UINT_MAX.
struct stat info;
if (stat(filename, &info) != 0)
return -1;
size_t filesize = (size_t)info.st_size;
// Allocate memory for reading the file
char* content = (char*)malloc(filesize);
if (content == NULL)
return -2;
// Open the file for reading
FILE* fptr = fopen(filename, "rb");
if (fptr == NULL)
return -3;
// Read the file and close it - we assume the filesize is not bigger than UINT_MAX.
size_t count = fread(content, filesize, 1, fptr);
fclose(fptr);
if (count != 1)
return -4;
// Remove all '\r' characters followed by a '\n' character
size_t newsize = 0;
for (long i = 0; i < filesize; ++i) {
char ch = content[i];
char ch2 = (i < filesize - 1) ? content[i + 1] : 0;
if (ch == '\r' && ch2 == '\n') {
ch = '\n';
++i;
}
content[newsize++] = ch;
}
// Test if we found any
if (newsize != filesize) {
// Open the file for writing and truncate it.
FILE* fptr = fopen(filename, "wb");
if (fptr == NULL)
return -5;
// Write the new output to the file. Note that if an error occurs,
// then we will lose the original contents of the file.
if (newsize > 0)
count = fwrite(content, newsize, 1, fptr);
fclose(fptr);
if (newsize > 0 && count != 1)
return -6;
}
// For a console application, we don't need to free the memory allocated
// with malloc(), but normally we should free it.
// Success
return 0;
} // main()
In my code I'm trying to read a file, read it's lines and get them into a String array, then print them and close the file. When I run it, it fails on a seg fault and skips the last line of the file, and I just can't find the problem...
My instinct is to blame reading the array wrongly or misbehaving with the file... Am I right?
Any help or redirects would be helpful.
Thank you!
Here is the main file:
#include "files_utils.h"
int main()
{
FILE *fp = fopen("expl", "r");
if (!fp)
return -1;
long lines_count = countlines(fp);
long flen = file_length(fp);
String *lines = calloc(lines_count, sizeof(String));
printf("file length: %ld\n", flen);
printf("file lines: %ld\n", lines_count);
getlines(lines, lines_count, fp);
printf("finished\n");
for (String *sp = lines; sp != NULL; sp++)
printf("%s", *sp);
printf("before close\n");
fclose(fp);
printf("closed\n");
return 0;
}
Here is the files_utils file:
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 10
typedef char *String;
long file_length(FILE *fp)
{
/*
find the length of the file fp points to, regardless of the current position.
*/
long original_pos = ftell(fp), i = 0;
rewind(fp);
// count chars:
for (int c = fgetc(fp); c != EOF; c = fgetc(fp))
i++;
// return the file to it's original position
fseek(fp, original_pos, SEEK_SET);
return i;
}
long countlines(FILE *fp)
{
/*
find the amount of lines in file fp points to, regardless of the current position.
*/
long original_pos = ftell(fp), i = 0;
rewind(fp);
// find newlines:
for (int c = fgetc(fp); c != EOF; c = fgetc(fp))
if (c == '\n')
i++;
// return the file to it's original position
fseek(fp, original_pos, SEEK_SET);
return i;
}
String *getlines(String lines[], long maxlines, FILE *fp)
{
for (int i = 0; i <= maxlines; i++)
{
lines[i] = calloc(MAXLINE, sizeof(char));
fgets(lines[i], MAXLINE, fp);
}
return lines;
}
And it outputs
file length: 144
file lines: 21
finished
... all the lines of the file except of the last one ...
Segmentation fault (core dumped)
The problem was fixed when I changed the printing loop to run until maxlines instead of waiting for NULL. Why is this? Why would waiting for NULL raise a seg fault?
I try to read a file character by character on C and i get Segmentation fault, no idea why and how can i debug it..
int textdump(const char *filename)
{
int count = 0;
FILE *file;
file = fopen(filename,"r");
char letter;
while(!feof(file)) {
letter = fgetc(file);
if (isprint(letter)) {
printf("%c",letter);
count++;
}
else {
printf("?");
}
}
fclose(file);
return count;
}
Okay, so your code has a bunch of mistakes that are common in beginner code.
Here's how to do it along the same lines, but hopefully fixing the errors:
size_t textdump(const char *filename)
{
size_t count = 0;
FILE * const file = fopen(filename, "rt");
if(file == NULL)
return 0;
while (1) {
const int ch = fgetc(file);
if(ch == EOF)
break;
if(isprint(ch) {
putc(ch, stdout);
++count;
}
else
putc('?', stdout);
}
fclose(file);
return count;
}
This:
Checks that the fopen() succeeds before relying on the file pointer being valid.
Uses the proper type for fgetc()'s return value, which is int.
Corrects the while(!feof() anti-pattern.
Uses fputc() for single-character output, lighter than printf().
Uses size_t to represent the count.
I'm not saying this is optimal, it still does single-character reading for instance (but buffered so it shouldn't be too bad). But it should be better.
I want to read this symbols with fgetc() ( I cant copy it, here link to file.txt )
This file is 2-byte long and its binary dump is 1A 98.
fgetc() cant read it and return -1. Please help((
for (int k = 0; k < fileSize; k++)
{
buffer[k] = (unsigned char) fgetc(f);
}
Picture of this symbols:
Maybe something with character encoding?
Your file contains 0x1A, which means EOF and reading it will stop reading when the file is opened in text mode.
Try opening your file in binary mode.
Here is a test code:
#include <stdio.h>
int main(void) {
const char *fileName = "codeText.txt";
FILE* fp;
int input;
fp = fopen(fileName, "r");
if (fp==NULL) return 1;
puts("text mode:");
while((input = getc(fp)) != EOF) printf("%02X\n", (unsigned int)input);
fclose(fp);
fp = fopen(fileName, "rb");
if (fp == NULL) return 1;
puts("binary mode:");
while((input = getc(fp)) != EOF) printf("%02X\n", (unsigned int)input);
fclose(fp);
return 0;
}
I am suppose to pass stream, which is a pointer, by reference. So I am passing this as a pointer to a pointer. Can someone please verify my code?
int main(int argc, char** argv)
{
FILE *stream;
printf("LINES: %d\n",scan(stream));
}
int scan(FILE *(*stream))
{
stream = fopen("names.txt", "r");
int ch = 0, lines=0;
while (!feof(*stream))
{
ch = fgetc(*stream);
if (ch == '\n')
{
lines++;
}
}
fclose(*stream);
return lines;
}
No output received.
Your code has design issues. What exactly do you want to achieve?
If you just want to count the lines, make the FILE * local to your function:
int count_lines(const char *filename)
{
FILE *stream = fopen(filename, "r");
int lines = 0;
while (1) {
int c = fgetc(stream);
if (c == EOF) break;
if (c == '\n') lines++;
}
fclose(stream);
return lines;
}
If you want to do a regular file operation (read, write, seek, rewind etc.) to a file that has already been opened with fopen, just pass the handle as FILE *:
int fget_non_space(FILE *stream)
{
int c;
do {
c = fgetc(stream);
} while (isspace(c));
return c;
}
In that case, both fopen and fclose are called outside this function. (You don't call fclose in your program, which you should, even if the operating system makes sure to close the file automatically after exiting.)
Passing a pointer to the file handle, FILE **, makes sense only if you want to change that file handle itself in the function, for example by calling fopen:
int fopen_to_read(FILE **FILE pstream, const char *fn)
{
*pstream = fopen(fn, "r");
return (*pstream != NULL) ? 0 : -1;
}
Even then, it would be better to return the file handle, as fopen does.
Your example code leaves the open filehandle accessible in main, but you don't do anything with it, you don't even close it. Is that what you want? I doubt it.
Use
int scan(FILE **stream) //no need for brackets
{
*stream = fopen("names.txt", "r"); //* is for dereferencing
if(*stream==NULL) // Checking the return value of fopen
{
printf("An error occured when opening 'names.txt'");
return -1;
}
int ch = 0, lines=0;
while ((ch = fgetc(*stream))!=EOF) //while(!feof) is wrong
{
if (ch == '\n')
{
lines++;
}
}
fclose(*stream); // Close the FILE stream after use
return lines;
}
int main(void)
{
FILE *stream;
printf("LINES: %d\n",scan(&stream)); //Pass address of `stream`. The address is of type `FILE**`
}
Replace
stream = fopen("names.txt", "r");
with
*stream = fopen("names.txt", "r");
Also
printf("LINES: %d\n",scan(stream));
with
printf("LINES: %d\n",scan(&stream));