update file based on a key in C - c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{
char name[10];
char size[6];
char timestamp[15];
};
int main ()
{
FILE *outfile;
// open file for writing
outfile = fopen ("ads.txt", "a");
if (outfile == NULL)
{
fprintf(stderr, "\nError opend file\n");
exit (1);
}
struct person input1 = {"runner", "100", "4376482682"};
//struct person input2 = {"maze", "300", "3232365436"};
// write struct to file
fwrite (&input1, sizeof(struct person), 1, outfile);
//fwrite (&input2, sizeof(struct person), 1, outfile);
if(fwrite != 0)
printf("contents to file written successfully !\n");
else
printf("error writing file !\n");
// close file
fclose (outfile);
FILE *infile;
struct person input;
infile = fopen ("ads.txt", "r");
if (infile == NULL)
{
fprintf(stderr, "\nError opening file\n");
exit (1);
}
// read file contents till end of file
char name[10] = "maze";
char size[6] = "500";
char timestamp[15] = "437838322";
int remaining_size = 100;
int alreadythere =0;
//unpcoming file size
int incoming_file_size = 200;
int target_file_size_toremove = incoming_file_size - remaining_size;
while(fread(&input, sizeof(struct person), 1, infile)){
if(target_file_size_toremove > 0) {
int x = atoi(input.size);
if(target_file_size_toremove < x) {
strcpy(input.name, name);
strcpy(input.size, size);
strcpy(input.timestamp, timestamp);
}
}else {
if(strcmp(input.name, name) == 0) { // if name is eqUAL
if(strcmp(input.size, size) != 0) {
strcpy(input.size, size);
}
if(strcmp(input.timestamp, timestamp) !=0) {
strcpy(input.timestamp, timestamp);
}
alreadythere = 1;
}
printf ("id = %s name = %s %s\n", input.name,
input.size, input.timestamp);
}
}
if(alreadythere == 0) {
struct person incoming = {name, size, timestamp};
fwrite (&incoming, sizeof(struct person), 1, outfile);
}
// close file
fclose (infile);
return 0;
}
The code is in C language. I want to update the size variable when name is equal to "maze". How I can do it, while reading from file?
first the data that is writing in file is -
runner 100 4376482682
maze 300 3232365436
After updating -
runner 100 4376482682
maze 100 3232365436
size should updated from 300 to 100.

I have fixed a number of small bugs in your code related to opening the file in correct mode and checking if fwrite and fread where successful. Then I added the part you where really asking: update the record "maze".
To update the record, we need to read it, change the value and write it back to the file exactly where we have read it. So before reading a record, we query the current file pointer with ftell and before writing, we call fseek to move the file pointer back to the place we read. A call to fflush (another fseek would do as well) is required so that the next fread take place at the correct position.
For testing, I added a third record after "maze" so that we can see - by looking at the file content - that we don't overwrite data.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{
char name[10];
char size[6];
char timestamp[15];
};
int main()
{
FILE* outfile;
// open file for writing binary
outfile = fopen("ads.txt", "wb");
if (outfile == NULL) {
fprintf(stderr, "\nError opening file\n");
exit(1);
}
struct person input1 = { "runner", "100", "4376482682" };
struct person input2 = { "maze", "300", "3232365436" };
struct person input3 = { "street", "400", "4232365486" };
// write struct to file, checking for success
if ((fwrite(&input1, sizeof(struct person), 1, outfile) != 1) ||
(fwrite(&input2, sizeof(struct person), 1, outfile) != 1) ||
(fwrite(&input3, sizeof(struct person), 1, outfile) != 1))
printf("error writing file !\n");
else
printf("contents to file written successfully !\n");
// close file
fclose(outfile);
FILE* infile;
struct person input;
// Open for both reading and writing, binary
infile = fopen("ads.txt", "r+b");
if (infile == NULL) {
fprintf(stderr, "\nError opening file for update\n");
exit(1);
}
// read file contents till end of file, update "maze"
while (1) {
long pos = ftell(infile);
if (pos < 0) {
fprintf(stderr, "\nError getting file position\n");
break;
}
if (fread(&input, sizeof(struct person), 1, infile) != 1)
break;
// update the value of size here, if name is equal to "maze"
printf("id = %s name = %s %s\n", input.name, input.size, input.timestamp);
if (strcmp(input.name, "maze") == 0) {
if (fseek(infile, pos, SEEK_SET) != 0) {
fprintf(stderr, "\nError moving file pointer\n");
break;
}
strcpy(input.size, "100");
if (fwrite(&input, sizeof(struct person), 1, infile) != 1) {
fprintf(stderr, "\nError writing file\n");
break;
}
// fflush() is required so that fread() take place a the correct position
if (fflush(infile) != 0) {
fprintf(stderr, "\nError flushing file\n");
break;
}
printf(" Updated id = %s name = %s %s\n", input.name, input.size, input.timestamp);
// Since this code update a single record, we could break the loop
}
}
// close file
fclose(infile);
return 0;
}

Related

Reverse .wav file in C, any error in there?

I've been making the program from CS50'x about reversing the .WAV files. Seems to work fine, however the cs50's check finds an error. Don't know where it is, the code seems to be alright and there I can't find any problem.
I tried to change 'i' - iterator in for-loop but when set as = infile_size - block_size the file won't be converted / reversed.
My code below:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "wav.h"
int check_format(WAVHEADER header);
int get_block_size(WAVHEADER header);
int main(int argc, char *argv[])
{
// Ensure proper usage
// TODO #1
// check if command-line arguments = argv[0], argv[1], argv[2] = 3 in sum
if (argc != 3)
{
if (argc < 3)
{
printf("not enough command-line args\n");
}
else
{
printf("too much command-line args\n");
}
return 1;
}
// remember filenames
char *infile = argv[1];
char *outfile = argv[2];
// open input file for reading
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("could not open the infile\n");
return 1;
}
// read header into an array
WAVHEADER header;
fread(&header, sizeof(header), 1, inptr);
// use check_format to ensure WAV format
check_format(header);
// open output file for writing
FILE *outptr = fopen(outfile, "w");
if (outptr == NULL)
{
printf("couldn't open the outfile\n");
fclose(inptr);
return 1;
}
// write header to file
fwrite(&header, sizeof(header), 1, outptr);
// use get_block_size to calculate size of block
int block_size = get_block_size(header);
printf("block_size: %i\n", block_size);
if (block_size < 0)
{
printf("block_size with no size\n");
return 1;
}
// write reversed audio to file
// 1. declare an array to store each block of audio
char *buffer = malloc(block_size * sizeof(char));
if (buffer == NULL)
{
printf("no memory location");
return 1;
}
// get the size of the input file
fseek(inptr, 0, SEEK_END);
long int infile_size = ftell(inptr);
printf("file_size: %li\n", infile_size);
// iterate through the input file audio data
for (long int i = infile_size; i >= 0; i -= block_size)
{
// move the file indicator to the start
fseek(inptr, i, SEEK_SET);
// read from inptr each size
fread(buffer, sizeof(char), block_size, inptr);
// write in outfile
fwrite(buffer, sizeof(char), block_size, outptr);
}
// free
free(buffer);
// close files:
fclose(inptr);
fclose(outptr);
}
int check_format(WAVHEADER header)
{
// TODO #4
if (header.format[0] == 'W' && header.format[1] == 'A' && header.format[2] == 'V' && header.format[3] == 'E')
{
printf("This is the type .wav\n");
return 0;
}
else
{
printf("File is not the type .wav\n");
return 1;
}
}
int get_block_size(WAVHEADER header)
{
// TODO #7
// check if channels are mono or audio
if (header.numChannels == 1 || header.numChannels == 2)
{
int block_size;
block_size = header.numChannels * (header.bitsPerSample / 8);
return block_size;
}
else
{
printf("Not supported\n");
return 1;
}
}
Thanks in advance!

How can I modify a record in a binary file?

Today i want to save data to binary file and then change some values in this file. But unfortunately I couldn't do it right. Maybe i have problem with overwrite value in my file! So i used this code for save data to file -
People people;
FILE* outfile;
outfile = fopen("person.dat", "w");
if (outfile == NULL)
{
fprintf(stderr, "\nError opened file\n");
exit(1);
}
for (int i = 0; i < 2; i++)
{
people.price = 1;
scanf("%s", people.name);
fwrite(&people, sizeof(struct People), 1, outfile);
}
if (fwrite != 0)
printf("contents to file written successfully !\n");
else
printf("error writing file !\n");
fclose(outfile);
Also People is a struct!
struct People {
int price;
char name[20];
};
And after i saved some information in file i tried to edit it using this code -
FILE* infile;
struct People input;
infile = fopen("person.dat", "rb+");
if (infile == NULL)
{
fprintf(stderr, "\nError opening file\n");
exit(1);
}
while (fread(&input, sizeof(struct People), 1, infile))
{
if (input.price == 1) {
fprintf(infile, "%d", 25);
}
}
fclose(infile);
So i want to change this values where price is 1 with 25? But I noticed that nothing changed in the file? Why? Maybe I would be wrong with fprintf(infile, "%d", 25);?
Sorry for my bad English!
You have to rewrite the entire structure using fwrite(). And before you do that, you have to seek to the beginning of the record that you just read, so you can write over it.
while (fread(&input, sizeof(struct People), 1, infile))
{
if (input.price == 1) {
fseek(infile, -(int)sizeof(struct People), SEEK_CUR);
input.price = 25;
fwrite(&input, sizeof(struct People), 1, infile);
fflush(infile);
}
}

C programming, copying from one file to another using command line arguments

This is my code
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc < 4) {
printf("Missing arguments\n");
return -1;
}
// Check if buffer is valid before reading anything
int bufferSize = atoi(argv[3]);
if (!bufferSize || bufferSize < 1) {
printf("Invalid buffer size\n");
return -1;
}
printf("*** Copying from '%s' to '%s' (Buffer size: %dB) ***\n",
argv[1], argv[2], bufferSize);
// READ SOURCE FILE
FILE *inputFile = fopen(argv[1], "r");
if (!inputFile) {
printf("Error opening source file\n");
return -1;
}
// READ DESTINATION FILE
FILE *outputFile = fopen(argv[2], "w");
if (!outputFile) {
printf("Error opening destination file\n");
return -1;
}
int buffer[bufferSize];
int bytes;
do {
bytes = fread(buffer, 1, bufferSize, inputFile);
if (fwrite(buffer, 1, bytes, outputFile) != bytes) {
printf("Error writing into destination file\n");
return -1;
}
} while (bytes > 0);
fclose(inputFile);
fclose(outputFile);
return 0;
}
But when I try to exe the file it doesn't work. What could be the problem?
Here's the command line:
/Users/jurajc/Documents/Program/C/L1\ 1/C_program/c_program file.txt fileCopy.txt 512
*** Copying from 'file.txt' to 'fileCopy.txt' (Buffer size: 512B) ***
Error opening source file
The input file file.txt cannot be opened: either because it is not present in the current directory or because you do not have read access to it.
You should output more informative error messages. Note also these problems:
if (!bufferSize || bufferSize < 1) is a redundant test. if (bufferSize < 1) is sufficient.
the error messages should be output to stderr
the files should be open in binary mode to reliably copy all file types on legacy systems.
the read/write loop is incorrect: you should stop when fread returns 0 before attempting to write 0 elements to the output file.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc < 4) {
fprintf(stderr, "Missing arguments\n");
return -1;
}
// Check if buffer is valid before reading anything
int bufferSize = atoi(argv[3]);
if (bufferSize < 1) {
fprintf(stderr, "Invalid buffer size: %s\n", argv[3]);
return -1;
}
printf("*** Copying from '%s' to '%s' (Buffer size: %dB) ***\n",
argv[1], argv[2], bufferSize);
// READ SOURCE FILE
FILE *inputFile = fopen(argv[1], "rb");
if (!inputFile) {
fprintf(stderr, "Error opening source file %s: %s\n",
argv[1], strerror(errno));
return -1;
}
// READ DESTINATION FILE
FILE *outputFile = fopen(argv[2], "wb");
if (!outputFile) {
fprintf(stderr, "Error opening destination file %s: %s\n",
argv[2], strerror(errno));
return -1;
}
int buffer[bufferSize];
int bytes;
while ((bytes = fread(buffer, 1, bufferSize, inputFile)) != 0) {
if (fwrite(buffer, 1, bytes, outputFile) != bytes) {
fprintf(stderr, "Error writing into destination file: %s\n", strerror(errno));
return -1;
}
}
fclose(inputFile);
fclose(outputFile);
return 0;
}

I am trying to print a txt file and it doesn't work in C homework

I'm writing code that's supposed to verify that a .txt file is a certain format.
I wrote my code as I saw in a tutorial and in the website
and for some reason my program doesn't even print my file.
Can you tell me what I'm doing wrong?
The code will do something far more complex, but I'm still trying to work on my basics.
Here's my code so far:
int main(int argc, char *argv[]) {
/* argv[0] = name of my running file
* argv[1] = the first file that i receive
*/
define MAXBUFLEN 4096
char source[MAXBUFLEN + 1];
int badReturnValue = 1;
char *error = "Error! trying to open the file ";
if (argc != 2) {
printf("please supply a file \n");
return badReturnValue;
}
char *fileName = argv[1];
FILE *fp = fopen(argv[1], "r"); /* "r" = open for reading */
if (fp != NULL) {
size_t newLen = fread(&source, sizeof(char), MAXBUFLEN, fp);
if (ferror(fp) != 0) {
printf("%s %s", error, fileName);
return badReturnValue;
}
int symbol;
while ((symbol = getc(fp)) != EOF) {
putchar(symbol);
}
printf("finish");
fclose(fp);
}
else {
printf("%s %s", error, fileName);
return badReturnValue;
}
}
I think you need a bit more explanations:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
// there might be a macro BUFLEN defined in stdio
// which size is optimized for reading in chunks.
// Test if avaiable otherwise define it
#ifndef BUFLEN
# define BUFLEN 4096
#endif
int main(int argc, char *argv[])
{
char source[BUFLEN];
char *filename;
FILE *fp;
size_t fpread, written;
char c;
int ret_fclose;
if (argc != 2) {
fprintf(stderr, "Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
// reset errno, just in case
errno = 0;
// work on copy
filename = malloc(strlen(argv[1]) + 1);
if (filename == NULL) {
fprintf(stderr, "Allocating %zu bytes failed\n", strlen(argv[1]) + 1);
exit(EXIT_FAILURE);
}
filename = strcpy(filename, argv[1]);
// try to open the file at 'filename'
fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Opening file \"%s\" filename failed\n", filename);
// errno might got set to something usable, check and print
if (errno != 0) {
fprintf(stderr, "Error: %s\n", strerror(errno));
}
exit(EXIT_FAILURE);
}
// You have two options here. One is to read in chunks of MAXBUFLEN
while ((fpread = fread(&source, 1, BUFLEN, fp)) > 0) {
// Do something with the stuff we read into "source"
// we do nothing with it here, we just write to stdout
written = fwrite(&source, 1, fpread, stdout);
// you can use 'written' for error check when writing to an actual file
// but it is unlikely (but not impossible!) with stdout
// test if we wrote what we read
if ((fpread - written) != 0) {
fprintf(stderr, "We did not write what we read. Diff: %d\n",
(int) (fpread - written));
}
}
// fread() does not distinguish between EOF and error, we have to check by hand
if (feof(fp)) {
// we have read all, exit
puts("\n\n\tfinish\n");
// No, wait, we want to do it again in a different way, so: no exit
// exit(EXIT_SUCCESS);
} else {
// some error may have occured, check
if (ferror(fp)) {
fprintf(stderr, "Something bad happend while reading \"%s\"\n", filename);
if (errno != 0) {
fprintf(stderr, "Error: %s\n", strerror(errno));
}
exit(EXIT_FAILURE);
}
}
// the other way is to read it byte by byte
// reset the filepointers/errors et al.
rewind(fp);
// rewind() should have reseted errno, but better be safe than sorry
errno = 0;
printf("\n\n\tread and print \"%s\" again\n\n\n\n", filename);
// read one byte and print it until end of file
while ((c = fgetc(fp)) != EOF) {
// just print. Gathering them into "source" is left as an exercise
fputc(c, stdout);
}
// clean up
errno = 0;
ret_fclose = fclose(fp);
// even fclose() might fail
if (ret_fclose == EOF) {
fprintf(stderr, "Something bad happend while closing \"%s\"\n", filename);
if (errno != 0) {
fprintf(stderr, "Error: %s\n", strerror(errno));
}
exit(EXIT_FAILURE);
}
// The macros EXIT_FAILURE and EXIT_SUCCESS are set to the correct values for
// the OS to tell it if we had an eror or not.
// Using exit() is noot necessary here but there exits teh function atexit()
// that runs a given function (e.g: clean up, safe content etc.) when called
exit(EXIT_SUCCESS);
}
You read from the file twice but only print once.
If the file is to small the first reading will read all of the contents, and the second reading will not produce anything so you don't print anything.
I believe you have to reset the pointer after using fread.
Try fseek(fp, SEEK_SET, 0) to reset the pointer to the beginning of the file. Then print the file.

C: fgets always NULL

I'm playing with file I/O in C.. I'm trying to use fgets to read data in from one file and output it to another file. The problem is that it always returns NULL and so nothing gets copied to the output file. Here's my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fpIn;
FILE *fpOut;
if ((fpIn = fopen("C:\\testIn.txt", "r") == NULL))
{
printf("Cannot open input file!\n");
exit(1);
}
if ((fpOut = fopen("C:\\testOut.txt", "a") == NULL))
{
printf("Cannot open output file!\n");
exit(1);
}
char buffer[128];
while (fgets(buffer, 128, fpIn) != NULL)
{
fputs(buffer, fpOut);
}
fclose(fpIn);
fclose(fpOut);
system("PAUSE");
return 0;
}
another thing; when I tried using "a+f" in the second arg for fopen, it didn't work.
if ((fpOut = fopen("C:\\testOut.txt", "a") == NULL))
Should be
if ((fpOut = fopen("C:\\testOut.txt", "a")) == NULL)
Same on the input file.
If you are new to C, I'd suggest do one thing at a time to make it easier to track down issues.
e.g.
fpOut = fopen("C:\\testOut.txt", "a");
if(fpOut == NULL) {
...

Resources