My Program Works Mostly, except for When I try to read the Total Data that was Entered
#include <stdio.h>
#include <string.h>
#define bufferSize 300
char name[50], gift[50], list[300], end[50], *result;
int i;
int main()
{
FILE *appendPlace = fopen("NamesAndGifts.txt", "a");
FILE *readData = fopen("NamesAndGifts.txt", "r"); //my place for reading data
printf("This is a Gift Entering System for 3 People Only\nThe Name of the Person then their Gift Description will be taken\nThe Gift Description is Basically the Gift Name");
while (strcmp(end, "END") != 0) {
printf("\nEnter Name of Person %d or type 'END' to Exit Sequence\n", i + 1);
scanf("%s", &end);
if (strcmp(end, "END") != 0) {
strcpy(name, end);
printf("Now Enter Gift Description (Gift Name) of Person %d\n", i + 1);
scanf("%s", &gift);
strcat(list, "\n");
strcat(list, "Name: ");
strcat(list, name);
strcat(list, "\n");
strcat(list, "Gift: ");
strcat(list, gift);
strcat(list, "\n");
}
i++;
}
printf("The Gift Entering System (Names and their respective Gifts) is Below:\n");
printf("%s", list);
fputs(list, appendPlace);
fclose(appendPlace);
//below I attempt to read file Data to be able to print file's Data into running program
fscanf(readData, "%s", result);
printf("\n\n\n\n\n\n\nTotal Data in File Below:\n%s", result);
fclose(readData);
}
I tried out doing just file reading, and it seems that reading from the file like that can only read data that is not separated by (space bar) or (enter)
Is there a way to Solve this?
So there are 2 problems in your code.
result has no memory allocated to it. Since it is a global variable, it is initialized to 0, aka a NULL pointer. So your scanf() sees that and the reading fails and so does printf() and prints "(null)". The solution there is to allocate memory in result either by making it a static array or by using malloc().
Even if you fix the first problem, however, it will still not work as expected as fscanf() will stop reading input after the first whitespace is encountered. Since you want the whole (file) input to be read, you have four options:
Read character by character (not advisable for performance reasons but perhaps the easiest to implement)
read line by line (fairly a standard way)
read chunk by chunk given some pre-allocated buffer or
read the whole file at once (not advised for big files)
The functions to use are fgetc(), getline(), fread(). Additionally, you can find the size of the file by following this question
Related
Today I decided to learn to code for the first time in my life. I decided to learn C. I have created a small program that checks a txt file for a specific value. If it finds that value then it will tell you that that specific value has been found.
What I would like to do is that I can put multiple files go through this program. I want this program to be able to scan all files in a folder for a specific string and display what files contain that string (basically a file index)
I just started today and I'm 15 years old so I don't know if my assumptions are correct on how this can be done and I'm sorry if it may sound stupid but I have been thinking of maybe creating a thread for every directory I put into this program and each thread individually runs that code on the single file and then it displays all the directories in which the string can be found.
I have been looking into threading but I don't quite understand it. Here's the working code for one file at a time. Does anyone know how to make this work as I want it?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
//searches for this string in a txt file
char searchforthis[200];
//file name to display at output
char ch, file_name[200];
FILE *fp;
//Asks for full directory of txt file (example: C:\users\...) and reads that file.
//fp is content of file
printf("Enter name of a file you wish to check:\n");
gets(file_name);
fp = fopen(file_name, "r"); // read mode
//If there's no data inside the file it displays following error message
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
//asks for string (what has to be searched)
printf("Enter what you want to search: \n");
scanf("%s", searchforthis);
char* p;
// Find first occurrence of searchforthis in fp
p = strstr(searchforthis, fp);
// Prints the result
if (p) {
printf("This Value was found in following file:\n%s", file_name);
} else
printf("This Value has not been found.\n");
fclose(fp);
return 0;
}
This line,
p = strstr(searchforthis, fp);
is wrong. strstr() is defined as, char *strstr(const char *haystack, const char *needle), no file pointers in it.
Forget about gets(), its prone to overflow, reference, Why is the gets function so dangerous that it should not be used?.
Your scanf("%s",...) is equally dangerous to using gets() as you don't limit the character to be read. Instead, you could re-format it as,
scanf("%199s", searchforthis); /* 199 characters + \0 to mark the end of the string */
Also check the return value of scanf() , in case an input error occurs, final code should look like this,
if (scanf("%199s", searchforthis) != 1)
{
exit(EXIT_FAILURE);
}
It is even better, if you use fgets() for this, though keep in mind that fgets() will also save the newline character in the buffer, you are going to have to strip it manually.
To actually perform checks on the file, you have to read the file line by line, by using a function like, fgets() or fscanf(), or POSIX getline() and then use strstr() on each line to determine if you have a match or not, something like this should work,
char *p;
char buff[500];
int flag = 0, lines = 1;
while (fgets(buff, sizeof(buff), fp) != NULL)
{
size_t len = strlen(buff); /* get the length of the string */
if (len > 0 && buff[len - 1] == '\n') /* check if the last character is the newline character */
{
buff[len - 1] = '\0'; /* place \0 in the place of \n */
}
p = strstr(buff, searchforthis);
if (p != NULL)
{
/* match - set flag to 1 */
flag = 1;
break;
}
}
if (flag == 0)
{
printf("This Value has not been found.\n");
}
else
{
printf("This Value was found in following file:\n%s", file_name);
}
flag is used to determine whether or not searchforthis exists in the file.
Side note, if the line contains more than 499 characters, you will need a larger buffer, or a different function, consider getline() for that case, or even a custom one reading character by character.
If you want to do this for multiple files, you have to place the whole process in a loop. For example,
for (int i = 0; i < 5; i++) /* this will execute 5 times */
{
printf("Enter name of a file you wish to check:\n");
...
}
I am trying to make it so you can write a multi line message and it will store it in a file of your choosing and to be done you enter ` but when I do this at the top there is a blank line printed. How can I prevent this?
#include <stdio.h>
char filename[BUFSIZ];
char input[BUFSIZ];
FILE *file;
int main() {
printf("What do you want to name the file?\n");
scanf("%s", filename);
printf("Enter the contents. Once you are done enter `\n");
scanf("%[^`]s", input);
file = fopen(filename, "w");
fprintf(file, "%s", input);
fclose(file);
}
Code:
/* multi.c
*/
#include <stdio.h>
#define BUFSIZE 1024
int main(void)
{
char filename[BUFSIZE];
char input[BUFSIZE];
FILE *fp;
/* using fprintf(stderr... is better because of output buffering.
* This way, we don't need the '\n' at the end for the string to
* appear in the console. You could also use:
*
* printf("Filename: "); fflush(stdout);
*/
fprintf(stderr, "Filename: ");
/* When you press ENTER, a '\n' will be created at the stdin buffer.
* However, this scanf() will NOT read it into #filename. So the '\n'
* is left in the buffer...
*/
scanf("%s", filename);
fprintf(stderr, "Contents: ");
/* when you call scanf() again, the old '\n' is the first character
* it reads into #input. So, to discard that, simply add a space
* before the % - this ignores whitespaces (tabs, newlines, spaces)
*/
scanf(" %[^`]", input);
/* open the file, check for errors */
if(!(fp = fopen(filename, "w"))) {
perror("fopen");
return -1;
}
/* print the contents to the file */
fprintf(fp, "%s", input);
/* clean up */
fclose(fp);
return 0;
}
This is the execution:
$ ./multi
Filename: hello.txt
Contents: My name is Enzo
I am writing some multiline content to a file
And then I'm posting it to
Stack Overflow.`
And this is hello.txt
$ cat hello.txt
My name is Enzo
I am writing some multiline content to a file
And then I'm posting it to
Stack Overflow.$
Notice that after the last line my terminal character $ is there. This is because we end the input with a ` character, and not with a new line. Therefore, there's no new-line at the end of the file.
int main() {
printf("What do you want to name the file?\n");
scanf(" %s", filename);
printf("Enter the contents. Once you are done enter `\n");
scanf(" %[^`]s", input); //do not forget to put a space in scanf
file = fopen(filename, "w");
fprintf(file, " %s", input); //try to make a space in there or if it doesn't work
fclose(file); //than try " %[^\n] but this is a little risky depends in the way you want use the code.
//if none of these works than try this other way "\b %s"
}
always put a white space before " %s" or other text format specificators because, you may have problems...
The reason is that when you add a scanf() directely after a printf() sometimes it scanf takes as part of the string that it has to read even the last character printed by printf(), depending in what kind of characters they are (mostly white spaces, \n, \t). It's a little bit weird but it happened me a lot of times in the past.
I think that the problem is in there
scanf(" %[^`]s", input); //put that white space
first try to make that space here and I think it will work, but if it doesn't try the others left in comments. One of them will definitively work.
So I've written a program that will take in a information about a dvd (specifically it's postion, IDkey(just some random number) Title, Genre and Year of release), and using a struct it will write that info to a .txt file called "person.txt". I'm positive my code works for the most part but when I go to test it the output received in the .txt file is written in some weird symbol language and not English and quite frankly I have no idea as to why this is. Any explanation on why this is happening would be much appreciated, thanks :)
PROGRAM
#include <stdio.h>
#include <stdlib.h>
// a struct to read and write
struct dvd
{
int fposition;
int fIdKey;
char ftitle[50];
char fgenre[50];
int fyear;
};
int main ()
{
FILE *outfile;
struct dvd input;
// open file for writing
outfile = fopen ("person.txt", "w");
if (outfile == NULL)
{
fprintf(stderr, "\nError opend file\n");
exit (1);
}
printf("Postion: ");
scanf("%d", &input.fposition);
printf("ID Key: ");
scanf("%d", &input.fIdKey);
printf("Title: ");
scanf("%s",&input.ftitle);
printf("Genre: ");
scanf("%s", &input.fgenre);
printf("Year: ");
scanf("%d", &input.fyear);
// write struct to file
fwrite (&input, sizeof(struct dvd), 1, outfile);
if(fwrite != 0)
printf("contents to file written successfully !\n");
else
printf("error writing file !\n");
// close file
fclose (outfile);
return 0;
}
TEST RUN
TEST RUN OUTPUT IN THE .TXT FILE
You are writing these values to the file:
int fposition;
int fIdKey;
char ftitle[50];
char fgenre[50];
int fyear;
But you are displaying the whole file as characters. That kind of works for ftitle and fgenre because they really are characters...though since you don't populate all 50 characters there are some ugly uninitialized characters shown as well. That is easy to fix: just fill the unused characters (as well as the null terminator) with some known character (such as space) before writing to the file, or do not write the unused characters at all. You can use strlen() to find the length of each string and memset() to set the unused characters to a well-known character which is printable.
Next, saving an int and reading it as text is problematic. You need to decide on a single format. Either you write as integers like now, and you read as integers (which means you need a special program to read the file), or you commit to writing only text to the file.
Easiest might be to only write text to the file. You can use fprintf() for that, instead of fwrite(). You can use fprintf() for the character arrays as well, it will automatically write only the "used" part of each string up to the null terminator, skipping all the "garbage" characters.
I'm sorry to do this kind of question (because there is so much on internet about that) but I have to ask this:
The exercise involve reading from a file with a list of students (a record contains: name, surname and serial number). I've already created the document and consist of 13 lines, but when I write on terminal ./a.out, the output is a list of 13 lines of this type: (null) (null) (null)
The code is:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define EOF (-1)
#define BUF 100
typedef struct stud{
char *surname;
char *name;
char *serial;
} student;
int main(void){
FILE *fd;
int n = BUF;
int k = 0;
int i = 0;
int ret;
char *s = malloc(BUF * sizeof(char));
if((fd = fopen("registry_office_students.txt","r")) == NULL){
perror("error opening file");
return -1;
}
while(fgets(s,n,fd)!=NULL){
k++;
}
student *a = malloc(k*sizeof(student));
rewind(fd);
ret = fscanf(fd, "%s, %s, %s", a[i].surname, a[i].name, a[i].serial);
while(fscanf(fd, "%s, %s, %s", a[i].surname, a[i].name, a[i].serial) == ret){
i++;
}
for(i=0;i<k;i++){
printf("%s, %s, %s \n", a[i].surname, a[i].name, a[i].serial);
}
fclose(fd);
return 0;
}
I apologize again and hope for a proper response, Thanks.
fscanf(3) with %s won't allocate any memory for a string. That string should already exist.
At least, replace
ret = fscanf(fd, "%s, %s, %s",
a[i].surname, a[i].name, a[i].serial);
with something like
{
char surname[48];
char name[64];
char serial[32];
memset (surname, 0, sizeof(surname));
memset (name, 0, sizeof(name));
memset (serial, 0, sizeof(serial));
memset (a+i, 0, sizeof(struct stud));
ret = fscanf(fd, "%47s, %63s, %31s", surname, name, serial);
if (ret==3) {
a[i].surname = strdup(surname);
if (!a[i].surname)
{ perror("strdup surname"); exit(EXIT_FAILURE); }
a[i].name = strdup(name);
if (!a[i].name)
{ perror("strdup name"); exit(EXIT_FAILURE); }
a[i].serial = strdup(serial);
if (!a[i].serial)
{ perror("strdup serial"); exit(EXIT_FAILURE); }
}
}
Notice that I am clearing memory before reading it. I am explicitly giving size of strings in format of fscanf. I am duplicating with a tested strdup the read strings into heap.
Actually, I believe your approach could be wrong. You might decide that each student should be on a single line, which you would read with getline(3) and parse with sscanf(3) (maybe %n would be useful!) or maybe strtok (or "manually" using isalpha)
Please, read more material about C programming, then compile with all warnings and debug info (gcc -Wall -g), learn to use the debugger (gdb) and the memory leak detector (valgrind).
Firstly, you never allocate memory for the strings stored inside your structs. I.e. your fscanf attempts to read data into buffers that don't exist.
Secondly, your reading code reads data into a[0] twice. I.e. the first fscanf will read the first record in a[0] and then the next fscanf will read the next record into a[0] again, overriding what was read previously. Why? Was that your intent (like skipping a table header or something like that)?
Thirdly, your counting code (fgets) is not the same as your reading code (fscanf). If the reading code fails prematurely for fscanf-specific reason, you will read less than k records. Yet your printing code prints all k of them unconditionally. (What if your reading code failed immediately due to some error in fscanf format? In that case you never read anything.)
Fourthly, each call to fgets in your counting code is limited by 100 characters or by a newline (that's how fgets works). This is completely non-synchronized with how fscanf works, which is not limited by anything in your case. This means that the number of records seen by the counting code might easily end up different (greater) than the number of records seen by the reading code.
I'm having issues trying to read a white space character in C. What I want to do is read user input when asking for a first and last name.
So for example, I prompt the user to enter their name, they type in something like "Peter Smith". With that info, I want to write it to a file.
When it writes it to a file, the file only reads the last name "Smith". How can I read the whole string?
Here's how I asked:
printf("\nPlease enter your first and last name: \n");
scanf("%[^\n]", name);
fgets(name, sizeof(name), stdin);
I don't think your problem lies in the snippet you posted. Here's an example program I wrote on my Linux system to try and pinpoint the issue:
#include <stdio.h>
int main()
{
char name[128];
int num_scans = 0;
FILE *out = fopen("name.txt", "w");
if(out == NULL)
{
printf("Failed to open file for write.\n");
return 1;
}
printf("\nPlease enter your first and last name: \n");
num_scans = scanf("%127[^\n]", name);
if(num_scans < 1)
{
printf("Error reading name.\n");
return 2;
}
fprintf(out, "%s\n", name);
fclose(out);
return 0;
}
This appeared to work for me:
$cat name.txt
Peter Smith
If you post the code you used to write the name to a file, that might reveal the source of the error.
The code is working correctly. The fgets call replaces the value you read for the first name.
You should stick to one scheme of input. When you switch between input paradigms "strange" things happen. (Technically they are exactly what is supposed to happen, but typical users tend to not be too precise about exactly how each function works, and what state the input stream is left in.)