I need to convert a text file of the following format to binary file.
The input file only contains characters A, B, C or D. 'A' changes to '00','B' changes to '01', C changes to '10', D changes to '11'.
Sample input file:
ABBCDA
BBAABCD
BACBB
Sample output file:
000101101100
01010000011011
0100100101
I have wrote the following code, but it doesn't work.
int main()
{
FILE * fop;
FILE * fout;
int length=0;
int i;
char buffer[1000];
fop = fopen("filename.txt","r");
fout = fopen("filename.bin", "wb");
while(!feof(fop))
{
fgets(buffer,1000,fop);
length = strlen(buffer)-1;
for(i=0; i<length; i++)
{
if(buffer[i]=='A')
strcpy(buffer[i],'00');
if(buffer[i]=='B')
strcpy(buffer[i],'01');
if(buffer[i]=='C')
strcpy(buffer[i],'10');
if(buffer[i]=='D')
strcpy(buffer[i],'11');
}
fwrite(buffer, 1, sizeof(char)*length, fout);
fwrite("\n",1,sizeof(char),fout);
}
fclose(fop);
fclose(fout);
return 0;
}
What's wrong? How to solve it? Thank you.
This is the part to be fixed
while(fgets(buffer,1000,fop))
{
length = strlen(buffer)-1;
char sout[3];
for(i=0; i<length; i++)
{
*sout = '\0';
if(buffer[i]=='A')
strcpy(sout,"00");
if(buffer[i]=='B')
strcpy(sout,"01");
if(buffer[i]=='C')
strcpy(sout,"10");
if(buffer[i]=='D')
strcpy(sout,"11");
fwrite(sout, 1, strlen(sout), fout);
}
fwrite("\n",1,sizeof(char),fout);
}
Notes
the fgets within the while condition
sout to store temporarily the 2-bits (as string)
fwrite writes to sout (does not overwrite buffer), and is integrated within the for loop while the writing of \n is outside.
Version to write actual bytes (in binary) ...
while(fgets(buffer,1000,fop))
{
length = strlen(buffer)-1;
for(i=0; i<length; i++)
{
unsigned char byte = 0;
if(buffer[i]=='A')
byte = 0x0;
if(buffer[i]=='B')
byte = 0x1;
if(buffer[i]=='C')
byte = 0x2;
if(buffer[i]=='D')
byte = 0x3;
fwrite(&byte, 1, 1, fout);
}
// no more : fwrite("\n",1,sizeof(char),fout);
}
Using 0x notation to show I'm dealing with binary stuff...
And version David C. Rankin (perfectionist!)
while (fgets (buf, MAXC, fop)) { /* read each line */
char *p = buf; /* pointer to buf */
while (*p) { /* while not '\0' */
uint8_t byte = 0; /* declare byte */
if ('A' <= *p && *p <= 'Z') /* if char is A-Z */
byte = *p - 'A'; /* encode 0 - 25 */
else
byte = *p; /* write char as is */
if (fwrite (&byte, 1, 1, fout) != 1) { /* validate write */
fprintf (stderr, "error: write of '%c' failed.\n", *p);
goto badwrite; /* jump out of loops on fail */
}
p++; /* increment pointer */
}
}
badwrite:;
fclose (fop); /* close input file */
if (fclose (fout) == -1) /* close/validate output file */
fprintf (stderr, "error: on fout close.\n");
There is yet some stuff that can be improved, but for now ...
Related
I need to sum up the numbers from each line in the file like this e.g.:
1 2 3
10 -1 -3
and the result I should write to another file in each line likes this:
6
6
And I have the problem when in each line after the last number in reading file have more spaces, for example, maybe I use the '_' to show this problem:
When my function works:
10_11_12 '\n'
1_2_3 '\n'
and when my function doesn't work:
10_11_12_ _ _ '\n'
1_2_3 '\n'
I think I know where is the problem, but I have no idea how to fix it.
It's my function here:
int num=0;
char s;
while(fscanf(file, "%d", &num)==1){
fscanf(file, "%c", &s);
sum+=num;
if(s=='\n'){
fprintf(res_file, "%d\n", sum);
sum=0;
}
}
The problem is that fscanf is expecting a pointer to a char. Within your function, you are using a regular char, s.
char s;
You can fix your issue by making s a pointer. First, Allocate memory.
char *s = malloc(sizeof(char) + 1);
Now we can properly scan into the variable, s, and then check for the newline character. The only difference here is now we check for the newline by dereferencing s.
if (*s == '\n')
Don't forget to clean up the memory leak with free()!
free(s);
I was able to get the desired output using the code below.
#include <stdio.h>
#include <stdlib.h>
int processInputFile(char *filename)
{
FILE *ifp;
int buffer = 0;
char *newline = malloc(sizeof(char) + 1);
int sum = 0;
if ((ifp = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Failed to open \"%s \" in processInputFile.\n", filename);
return -1;
}
while(fscanf(ifp, "%d", &buffer) == 1)
{
fscanf(ifp, "%c", newline);
sum += buffer;
if (*newline == '\n')
{
printf("%d\n", sum);
sum = 0;
}
}
free (newline);
fclose(ifp);
}
int main(int argc, char **argv)
{
if (argc < 2)
{
printf("Proper syntax: ./a.out <n>\n");
return -1;
}
processInputFile(argv[1]);
return 0;
}
Any kind of line-by-line processing in C is easier done by reading the line first, and then processing it. fgets(3) handles end-of-line for you; then you just need to scan what it read. Plus, in the real world, some lines won't scan: either they'll have errors, or your scan won't be general enough. When that happens, it's awfully handy to write the input to standard error, so you can see what you're looking at.
Here's a complete program that does what you want. It assumes lines are less than 80 bytes long and doesn't protect against invalid input, though.
#include <stdio.h>
#include <err.h>
int main( int argc, char *argv[] ) {
char line[80];
static const char *filename = "sum.dat";
FILE *input;
if( (input = fopen(filename, "r")) == NULL ) {
err(1, "could not open %s", filename);
}
for( int nlines = 0;
fgets(line, sizeof(line), input) != NULL;
nlines++ )
{
double value, sum = 0;
int n;
for( char *p = line; sscanf(p, "%lf%n", &value, &n) > 0; p += n ) {
sum += value;
}
printf( "line %d: sum = %lf\n", nlines, sum );
}
return 0;
}
Reading with a line-oriented input function like fgets() or POSIX getline() ensures that a complete line of input is consumed on each call. (don't skimp on buffer size). strtol was created to convert an unknown number of values per-line into long. You walk-a-pointer down your buffer by utilizing the endptr parameter filled by strtol after a successful conversion to point to the next character after the last digit converted.
This allows a simple method to use a pair of pointers, p your start-pointer and ep your end-pointer to work through an entire line converting values as you go. The basic approach is to call strtol, validate it succeeded, and then set p = ep; to advance to the start of your next conversion. strtol ignores leading whitespace.
Putting it altogether, you could do:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
/* (don't skimp on buffer-size) */
int main (int argc, char **argv) {
char buf[MAXC]; /* buffer to hold each line read */
size_t n = 0; /* line-counter */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line */
char *p = buf, *ep = p; /* pointer and end-pointer */
int sum = 0; /* variable to hold sum */
if (*buf == '\n') /* ignore empty lines */
continue;
while (*p && *p != '\n') {
errno = 0;
long tmp = strtol (p, &ep, 0); /* convert to temp long */
if (p == ep) { /* validate digits were converted */
fputs ("error: no digits extracted.\n", stderr);
break;
}
else if (errno) { /* validate no under/overflow occurred */
fputs ("error: underflow/overflow occurred.\n", stderr);
break;
}
else if (tmp < INT_MIN || INT_MAX < tmp) { /* validate in range */
fputs ("error: tmp exceeds range of int.\n", stderr);
break;
}
sum += tmp; /* add tmp to sum */
p = ep; /* set p to end-ptr (one past last digit used) */
}
n++; /* advance line counter */
printf ("sum line [%2zu] : %d\n", n, sum); /* output sum */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
(note: the if (*buf == '\n') which tests if the first character in the line is a newline character and simple skips to the next line, no need to worry about converting values in a empty line)
Example Use/Output
Using your data in dat/sumlines.txt produces the expected results.
$ ./bin/sumline dat/sumlines.txt
sum line [ 1] : 6
sum line [ 2] : 6
Let me know if you have further questions.
I read some data from a file, and send it through a pipe. When I read the data from the pipe, sometimes there's extra characters inside. The extra characters are also inconsistent, but normally is an extra "R" at the end.
The data I read from the file is correct, as it is always as it should be. It's only after reading it from the pipe that I encounter problems.
Could you help me find the error? I've been staring at this for ages and I can't find it.
This is the part of my code that is giving me trouble.
Thanks for your help.
int main (int argc, char **argv) {
int nClients;
int file_name_HTML[2];
create_pipes(file_name_HTML, server_access_request);
init_free_pipes();
nClients = getHTMLFilesIntoPipe(file_name_HTML);
int clients[nClients];
for(int i=0; i < nClients; i++)
{
if((clients[i] = fork()) == 0)
{
clientFunction(file_name_HTML, server_access_request);
}
}
.....
}
int getHTMLFilesIntoPipe(int *file_name_HTML)
{
int i, n = 0;
char (*lines)[MAXCHAR] = NULL;
FILE *fp;
fp = fopen("./data/listado_html.txt", "r");
if (!fp) { /* valdiate file open for reading */
err_exit("error: file open failed.\n");
}
if (!(lines = malloc (MAXLINES * sizeof *lines))) {
err_exit("error: virtual memory exhausted 'lines'.\n");
}
while (n < MAXLINES && fgets (lines[n], MAXCHAR, fp)) /* read each line */
{
char *p = lines[n]; /* assign pointer */
for (; *p && *p != '\n'; p++) {} /* find 1st '\n' */
if (*p != '\n') /* check line read */
{
int c;
while ((c = fgetc (fp)) != '\n' && c != EOF) {} /* discard remainder of line with getchar */
}
*p = 0, n++; /* nul-termiante */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
for (int i = 0; i < n; i++)
{
write(file_name_HTML[WRITE], lines[i], strlen(lines[i]));
}
free(lines);
return n;
}
void clientFunction(int *file_name_HTML, int *server_access_request)
{
char fileName[MAXCHAR];
close(file_name_HTML[WRITE]);
//Read HTML file name
read(file_name_HTML[READ], fileName, MAXCHAR - 1);
printf("%s\n", fileName);
.......
}
Expected output:
abcd1.html
abcd2.html
abcd3.html
abcd4.html
abcd5.html
Current output:
abcd1.htmlR
abcd2.htmlR
abcd3.htmlR
abcd4.htmlR
abcd5.htmlR
It is because your string is not null(\0) terminated.
As you write to the pipe excluding null(\0) terminator.
write(file_name_HTML[WRITE], lines[i], strlen(lines[i])+1);
^--- +1 to include null character.
strlen returns the length excluding null terminator.
double a[5];
for(int i = 0; i < 5; ++i){
read(fd, &a[i], sizeof(double));
}
When I print the content of the array, it shows me only zeros. How can I read double numbers from a text file without using fscanf?
File.txt
2.00 5.11 6.90 3.4 8.7
If I read char by char until the end of line, everything is fine.
As suggested by others if you don't want to use fscanf() then probably you should read all data from file using read() and store into char buffer and parse upto whitespace and then use strtod() to convert resultant string into double.
Here is the helping solution not complete one
int main() {
int fd = open("input.txt",O_RDWR | 0664);
if(fd == -1) {
perror("open");
return 0;
}
/* first find the size of file */
int size = lseek(fd,0,2);
printf("size of file : %d \n",size);
lseek(fd,0,0);/* again start reading from beginning */
/* take buffer equal to size of file */
char *buf = malloc(size * sizeof(char) + 1);
/* read all at a time using read()*/
read(fd,buf,size);
buf[size] = '\0';
printf("%s\n",buf);
/* now parse using strtod() */
double res;
char new_buf[64]; /* to store each double number read from fil
e */
for(int iter = 0,inner_iter = 0;buf[iter] != '\0' ;iter++ ) {
if(buf[inner_iter]!=' ' ) {
new_buf[inner_iter++] = buf[iter];
continue;
}
else {
new_buf[inner_iter] = '\0';
res = strtod(new_buf,NULL);
printf("%lf\n",res);
inner_iter = 0; /* make this variable 0 again */
}
}
free(buf);
close(fd);
return 0;
}
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;
}
I have written some code to read each lines of textfile to 2d array.
/* FileProcess.c library */
#define LINE_SIZE 128 /* Max line's length = 256 characters */
extern ulong
File_ReadLine (FILE *fptr,
char **result)
{
char buff_line[LINE_SIZE], *p;
ulong nLines = 0UL;
/* Check if fptr is readable */
if (fptr == NULL) {
printf("File not found.\n");
return -1;
}
/*get number of lines; from http://stackoverflow.com/a/3837983 */
while (fgets(buff_line, LINE_SIZE, fptr))
if (!(strlen(buff_line) == LINE_SIZE-1 && buff_line[LINE_SIZE-2] != '\n'))
nLines++;
/* Allocating memory for result */
result = malloc(nLines * sizeof(char *)); //
/* Pointer return to begin of file */
rewind(fptr);
/* Getting lines */
int i = 0;
while (!feof(fptr)) {
/* Get current line to buff_line */
fgets(buff_line, LINE_SIZE, fptr);
/* Replace '\n' at the end of line */
char *c = strchr(buff_line, '\n');
if (c != NULL)
*c = '\0';
/* Handle '\n' at the end of file */
if (feof(fptr))
break;
/* Memory allocate for p */
result[i] = malloc (LINE_SIZE * sizeof(char));
/* Copy buff_line to p */
strcpy(result[i], buff_line);
i++;
}
return (nLines);
}
main program:
int main ()
{
char **Phone;
FILE *fptr;
fptr = fopen("phone.na.txt", "r");
ulong nLines = File_ReadLine(fptr, Phone);
printf("%ld\n", nLines);
int i;
for (i = 0; i < nLines; i++) {
printf("%s", Phone[i]);
}
fclose(fptr);
return 1;
}
Using gdb, running line by line, program return segmentation fault after
printf("%s", Phone[i]);
So I can't understand why segmentation fault here? Are there any errors with malloc() ?
I haven't compiled or run the code, but I think the problem is in your line counter:
while (fgets(buff_line, LINE_SIZE, fptr))
if (!(strlen(buff_line) == LINE_SIZE-1 && buff_line[LINE_SIZE-2] != '\n'))
nLines++;
What you're saying here is unless "the string length of buff_line is equal to LINE_SIZE -1 and the character at buff_line[LINE_SIZE-1] is not equal to '\n'", increment nLines.
So... whenever you read a line out of your text file which ends with '\n', and that line is 127 characters long, you're not going to increment nLines. You malloc spaces for nLines, but you're probably going to read more than nLines of data from your file... at that point, you're writing more into **result than you have allocated, and bad things are going to happen.