I have the following code that converts a stream data of 16-bit integer to unsigned 8-bit integer.
I am looking to convert them to alphabetical data values and see what they contain.
#include<stdio.h>
int main() {
FILE *fp,*out;
char buffer[256];
size_t i = 0;
fp=fopen("c:/Gosam/input.txt", "rb");
if(fp != NULL) {
fread(buffer, sizeof buffer,1, fp);
}
out = fopen("c:/Gosam/res.txt", "w");
if(out != NULL) {
// buffer = (char*) malloc (sizeof(char)*Size);
for( i = 0; i < sizeof(buffer); i += 2)
{
const unsigned int var = buffer[i] + 256 * buffer[i + 1];
fprintf(out, "%u\n", var);
}
fclose(out);
}
fclose(fp);
}
The following is the form of my output:
263 4294966987 4294967222 4294967032 64 4294967013 73 4294967004 90
4294967028 83 4294966975 37 4294966961 5 4294966976 82 4294966942
4294967022 4294966994 11 4294967024 29 4294966985 4294966986 4294966954 50
4294966993 4294966974 4294967019 4294967007
This are the values I want to convert to alphabetical characters and see their content.
I don't know what you expect as an answer (you didn't ask a question), but there seems to be one suspicious thing in your code:
char buffer[256];
Here char means signed char. If your code does manipulations on them (like multiplying by 256), it probably doesn't do what you expect (though I can only guess what you expect - your question doesn't mention it).
Try the following:
unsigned char buffer[256];
Also please ask a question (that is, something with a question mark), and give some examples (input, output).
Your basic mistakes were:
after opening the inputfile checking out instead of fp against NULL
fread until eof won't return the number of characters that could be read (I've used fseek and ftell for this purpose)
writing uint values instead of char values to your file
I've fixed them and commented the affected lines appropriate. I also changed the buffer to use dynamic memory allocation instead of static allocation (that's how you can allocate memory for a buffer of a size that is unknown at compile-time). Please try the following code, which will copy all ASCII characters from one file to your output file (which is probably what you meant by 'alphabetical strings'):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
FILE *fp, *out;
char *buffer = NULL; /* use a pointer for dynamic memory allocation */
size_t i = 0, charCount = 0;
fp = fopen("c:/input.txt", "r"); /*read as ascii - not binary */
if(fp != NULL){ /*use 'fp' here 'out' is not initalized */
fseek(fp, 0, SEEK_END); /* go to end of the file */
charCount = ftell(fp) - 1; /* get position */
fseek(fp, 0, SEEK_SET); /* return to the beginning of the file */
buffer = (char*)malloc(sizeof(char)*charCount); /* allocate memory */
fread(buffer, sizeof(char) * charCount, 1, fp); /* reads all characters from the file */
}
out = fopen("c:/output.txt", "w");
if(out != NULL){
for(i = 0; i < charCount; i += 1){ /* loop from 0 to count of characters */
const unsigned char var = buffer[i];
fprintf(out, "%c", var);
}
fclose(out);
}
fclose(fp);
if(buffer != NULL){
free(buffer); /* deallocate memory */
}
return 0;
}
Related
char* freadline(FILE* fp){
fseek(fp, 0, SEEK_END);
int lSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buffer = malloc(lSize);
fread(buffer, 1, lSize, fp);
fgets(buffer, sizeof(lSize), fp);
return buffer;
}
but it doesn't read line by line any suggestions as to how this would be read line by line
There are couple solutions here.
The first is to get the size of the entire file using fseek and ftell fseek will allow you to go to the end of file and ftell will give you the current position which can be used as a size indicator. You can then allocate enough of a buffer to read the entire file then split them up into lines.
The other solution is to use a temporary buffer of 1000 or so like you're already doing, read a character at a time using fgetc in a loop and feed it into the temporary buffer until you hit a new line indicator , then use the strlen method to get the length and allocate a buffer of that size, copy the temporary buffer then return the allocated buffer.
There is also errors in your code as pointed out in the comments. You're discarding your allocated memory resulting in a leak. And your freadline doesn't actually read a line it just reads whatever size you're telling it to read.
the lines in the file could be of any length.
realloc() is a classic approach, but how about a simple, slow and plodding one:
Read once to find line length, seek, allocate, then read again to save the line.
#include <stdio.h>
char* freadline(FILE *fp) {
int length = 0;
long offset = ftell(fp);
if (offset == -1)
return NULL;
int scan_count = fscanf(fp, "%*[^\n]%n", &length); // Save scan length
if (scan_count == EOF)
return NULL;
if (fseek(fp, offset, SEEK_SET))
return NULL;
size_t n = length + 1u; // +1 for potential \n
char *buf = malloc(n + 1); // + 1 for \0
if (buf == NULL)
return NULL;
size_t len = fread(buf, 1, n, fp);
buf[len] = '\0';
return buf;
}
Test
#include <assert.h>
#include <stdlib.h>
int main() {
FILE *fp = fopen("tmp.txt", "w+");
assert(fp);
for (int i = 0; i < 10; i++) {
int l = i * 7;
for (int j = 0; j < l; j++) {
fputc(rand() % 26 + 'a', fp);
}
fputc('\n', fp);
}
rewind(fp);
char *s;
while ((s = freadline(fp)) != NULL) {
printf("<%s>", s);
free(s);
}
fclose(fp);
return 0;
}
Output
<
><lvqdyoq
><ykfdbxnqdquhyd
><jaeebzqmtblcabwgmscrn
><oiaftlfpcuqffaxozqegxmwgglkh
><vxtdhnzqankyprbwteazdafeqxtijjtkwea
><zqgmplohyxrutojvbzllqgjaidbtqibygdzcxkujvw
><ghwbmjjmbpksnzkgzgiluiggpkzwhaetclrcyxcsixsutjmrm
><vqlybsjnihnfqyfhyszwgpsvnhnngdnjzjypqcflnztrhcfgbkakzxam
><alsuauxxchqjxqaiddtjszgcbullyyjymytioyawpzshhfpqpsatddbcagjgobm
>
If you're ok targeting POSIX, it already has a function that does what you need: getline.
#include <stdio.h>
#include <stdlib.h>
FILE *fh = ...;
char *line = NULL;
size_t buf_size = 0;
while (1) {
ssize_t line_len = getline(&line, &buf_size, fh);
if (line_len == -1)
break;
// ...
}
free(line);
If not, getline can be implemented using using fgets and realloc in a loop. Just start with a arbitrarily-sized buffer.
The following program finds and deletes words that begin and end with the same character. It works just fine, except I decided to take the code for printing result text in from deleteWords() and put it inside of main(). Therefore, the *fpOut parameter in became redundant in deleteWords(). Deleting the parameter results in
/bin/sh: line 1: 1371 Segmentation fault: 11 ./main duom.txt rez.txt make: *** [main] Error 139
However if I compile it and run it any third parameter (e.g. int useless argument instead of FILE *fpOut), it works without errors.
Has anybody have a clue what could be causing this problem?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int checker (char zodis[]) {
size_t last = strlen(zodis);
if (zodis[0] == zodis[last-1])
return 0;
return 1;
}
void memAlloc (char **text, char **buffer, FILE **fp, char *fileName) {
int fileLength;
*fp = fopen(fileName, "r");
fseek(*fp, 0L, SEEK_END);
fileLength = fseek(*fp, 0L, SEEK_SET);
*text = malloc(fileLength * sizeof(char));
*buffer = malloc(fileLength * sizeof(char));
}
void deleteWords (FILE *fp, int anyUselessParameter, char *buffer) {
char *text;
while (fscanf(fp, "%s", text) == 1) {
if (checker(text)) {
printf("%s ", text);
sprintf(buffer + strlen(buffer), "%s ", text);
}
}
printf("\n");
}
int main(int argc, char *argv[]) {
FILE *fp, *fpOut;
int anyUselessParameter;
char *text, *buffer, *inputFileName = argv[1], *outputFileName = argv[2];
if (argc < 2)
return 0;
fpOut = fopen(outputFileName, "w");
memAlloc(&text, &buffer, &fp, inputFileName);
deleteWords(fp, anyUselessParameter, buffer);
fputs(buffer, fpOut);
fclose(fp);
fclose(fpOut);
free(text);
return 0;
}
char *text;
while (fscanf(fp, "%s", text) == 1) {
scanf needs the buffer to be allocated. Here it dereferences an uninitialized pointer text and writes to it. scanf tries to write to text[0], text[1].. and so on, so accesses text out of bounds and undefined behavior happen.
*buffer = malloc(fileLength * sizeof(char));
...
sprintf(buffer + strlen(buffer), "%s ", text);
buffer is uninitialized, so strlen(buffer) will result in some undefined value. Explicitly initialize buffer[0] = '\0' if you wish to use strlen later. Also you don't include memory for terminating '\0' character inside your buffer.
As you are trying to read the file into a buffer, that is allocated using the file size
if (fread(buffer, fileLenght, 1, fp) != fileLength) { /* handle error */ }
If you have to, use snprintf instead of sprintf just to be safe. snprinttf(buffer+strlen(buffer), fileLength - strlen(buffer), ...);
Also, try to never use scanf without specifing field length inside %s modifier. You can try:
char text[256]; // or other maximum word length
while (fscanf(fp, "%255s", text) == 1) {
As you already have allocated memory for the file, you can use it as a parameter to scanf, if you have to. One would need to prepare the format string for scanf as argument - it is a bit hard. See below:
for (;;) {
// prepare scanf %s format modifier to use with printf to write to buffer end
char fmt[20];
size_t buffer_size = fileLenght;
size_t free_in_buffer = buffer_size - strlen(buffer);
snprintf(fmt, 20, "%%%ds", free_in_buffer);
// we will write here: up to free_in_buffer
char *in = buffer + strlen(buffer);
if (fscanf(fp, fmt, in) != 1) break;
// we now check the last readed word form the file
if (!checker(in)) {
// if the last readed word is bad, we can revert it
in[0] = '\0'
}
}
This is wrong:
fileLength = fseek(*fp, 0L, SEEK_SET);
Per POSIX:
RETURN VALUE
The fseek() and fseeko() functions shall return 0 if they
succeed.
Otherwise, they shall return -1 and set errno to indicate the error.
I have a large file containing floating point numbers and I want to read them.
52.881 49.779 21.641 37.230 23.417 7.506 120.190 1.240 79.167 82.397 126.502 47.377 112.583 124.590 103.339 5.821 24.566 38.916 42.576
This is just the beggining of the file. It has 10000000 numbers.
I got this code but I don't know how to print the numbers.
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <fcntl.h>
#include <sysexits.h>
#include <unistd.h>
int main()
{
int fd;
size_t bytes_read, bytes_expected = 1000000*sizeof(double);
double *data;
char *infile = "file.dat";
if ((fd = open(infile,O_RDONLY)) < 0)
err(EX_NOINPUT, "%s", infile);
if ((data = malloc(bytes_expected)) == NULL)
err(EX_OSERR, "data malloc");
bytes_read = read(fd, data, bytes_expected);
if (bytes_read != bytes_expected)
err(EX_DATAERR, "Read only %d of %d bytes",
bytes_read, bytes_expected);
/* print all */
free(data);
exit(EX_OK);
}
You are attempting to read a text file as if the data was binary, so you will read some bytes but the double values stored in the array will not be the values that you wanted to read from the file, you can probably do this
FILE *file;
double *array;
size_t count;
const char *infile = "file.dat";
file = fopen(infile, "r");
if (file == NULL)
return -1;
count = 0;
while (fscanf(file, "%*lf") == 1)
count += 1;
rewind(file);
array = malloc(count * sizeof(*array));
if (array == NULL) {
fprintf(stderr, "cannot allocate %zu bytes!\n", count * sizeof(*array));
fclose(file);
return -1;
}
// Read the values into the array
for (size_t i = 0; i < count; ++i) {
fscanf(file, "%lf", &array[i]);
}
// Print the array
for (size_t i = 0; i < count; ++i) {
fprintf(stdout, "%f\n", array[i]);
}
// Release memory
free(array);
Since you want a fast solution, maybe you have to sacrifice memory.
The faster manner of reading a file is in binary form.
Thus, I would obtain the file size with an efficient method,
then I would allocate memory accordingly,
with the idea of uploading the entire file to memory.
There, since memory reading is faster than file reading,
the data can be quickly read by using sscanf(...).
We can also observe that each floating point number
needs at least 3 characters to be stored in a text file:
1 char for the dot ('.'),
1 char for some digit,
and 1 char for
a space (' ') used to separating a value from its succesor in the
file.
Thus, the file size divided by 3 will be the upper bound for the size of the array of doubles.
#include <stdio.h>
int main(void) {
char *filename = "file.dat";
FILE *F = fopen(filename, "rb");
fseek(F, 0L, SEEK_END);
long int filesize = ftell(F);
rewind(F);
char *data = malloc(filesize+1);
fread(data, filesize, 1, F);
data[filesize] = '\0'; // End of string, just in case
fclose(F);
// The desired data will be stored in array:
double *array = malloc(sizeof(double) * filesize/3);
int ret;
int n; // represents the no chars in a sscanf(...) reading
double *a = array;
while (1) { // Infinite loop...
ret = sscanf(data, " %lg%n", a, &n);
if (ret == EOF) break; // <<---- EXIT POINT of the loop
a++;
data += n;
}
long int array_size = a - array + 1;
}
I have a data stream that contains binary data that is a I16 complex number.
I want to convert to a string representation in ANSI C.
I have tried the code below but it gives me the same binary output.
How else to do this?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
FILE *fp, *out;
char *buffer = NULL; /* use a pointer for dynamic memory allocation */
size_t i = 0, charCount = 0;
fp = fopen("c:/input.txt", "r"); /*read as ascii - not binary */
if(fp != NULL){ /*use 'fp' here 'out' is not initalized */
fseek(fp, 0, SEEK_END); /* go to end of the file */
charCount = ftell(fp) - 1; /* get position */
fseek(fp, 0, SEEK_SET); /* return to the beginning of the file */
buffer = (char*)malloc(sizeof(char)*charCount); /* allocate memory */
fread(buffer, sizeof(char) * charCount, 1, fp); /* reads all characters from the file */
}
out = fopen("c:/out.txt", "w");
if(out != NULL){
for(i = 0; i < charCount; i += 1){ /* loop from 0 to count of characters */
const unsigned char var = buffer[i];
fprintf(out, "%c", var);
}
fclose(out);
}
fclose(fp);
if(buffer != NULL){
free(buffer); /* deallocate memory */
}
return 0;
}
FILE *fp;
char *f_array[256];
int f_length;
int *a = 0;
fp = fopen("test.txt", "r");
fseek(fp, 0, SEEK_END);
f_length = ftell(fp);
printf("%d\n\n", f_length);
int n = 1, i = 0;
while (n > 0)
{
n = fscanf(fp, "%s", f_array[i]);
i++;
}
I am trying to copy the contents of a .txt file into a char* array. Much like what would happen with InternetReadFile and lpbuffer. However, I cannot seem to get this right. I need my array to be filled with the contents of the .txt file character by character. Any suggestions?
I need the array to be single-dimensional
The issue is mainly to do with your data types. You want to store the file in memory. That would be a character (byte) array, but you have created an "array of pointers":
char *f_array[256];
When you probably wanted just:
char f_array[256];
Then, to do as you asked and read character by character into that array, use fgetc. Note that fgetc will be far less efficient that just reading the whole file in a single function call with fread. The kernel:
while ( EOF != (c = fgetc( fp )) && ++i < MAX_LEN )
f_array[ i ] = c;
In context of a working example:
#include <stdio.h>
int main ( ) {
const size_t MAX_LEN = 255;
FILE * fp;
char f_array[ MAX_LEN +1];
int c;
size_t i = -1;
f_array[ MAX_LEN +1] = 0;
fp = fopen("test.txt","r");
if ( NULL == fp )
perror("Error opening file");
else {
while ( EOF != (c = fgetc( fp )) && ++i < MAX_LEN )
f_array[ i ] = c;
fclose (fp);
}
f_array[ i ] = 0;
printf("%zu bytes read\n\n", i);
printf("Content read:\n%s\n", f_array);
return 0;
}
You are calculating the length of the file but you don't use this information in
any way.
char *f_array[256];
This is an array of dimension 256 of pointers to char. f_array[i] is
uninitialized and it's pointing into the digital nirvana, passing it to
fscanf yields undefined behaviour. You would need to declare it as something
like this:
char f_array[255][255];
But then you are limiting yourself to max 255 strings, you are not storing it
into a single string. Also you are storing max. 255 words. Use fgets or
fread to get the whole content at once.
char file[f_length + 1];
rewind(fp);
fread(file, f_length, 1, fp);
file[f_length] = 0; // terminate the string
printf("Whole file is: %s\n", file);
Here you are storing the whole file in an array of chars. Also after setting
the file at the end, you'll need to rewind the file to the beginning, otherwise
you are not reading anything.