My code is not putting the text file data into line on the second pass of the while loop, and any subsequent pass. I'm sure it's a silly error but I cannot find it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fr;
char *line,*word,*vali;
ssize_t read;
int i=0,sum=0,len =0,flag=0;
const char delim[2]=" ";
int main(int argc, char* argv[])
{
line = (char *)malloc(sizeof(&len));
word = (char *)malloc(sizeof(&len));
vali = (char *)malloc(sizeof(&len));
fr = fopen(argv[1], "r");
if(fr==NULL)
{
exit(EXIT_FAILURE);
}
while ((read = getline(&line, &len, fr)) != -1)
{
printf("line is %s\n", line );
fscanf(fr,"%s%*[^\n]",word);
printf("%s ", word);
vali=strtok(line, delim);
while(vali != NULL)
{
sum=sum+atoi(vali);
vali = strtok(NULL, delim);
}
printf("%d\n", sum);
sum=0;
vali=" ";
len = strlen(line);
}
fclose(fr);
if (line)
free(line);
return 0;
}
If len is some integral type containing the desired length of the first line, then:
&len
Has type pointer-to-integer, and
sizeof(&len)
Returns the size of a pointer (8 bytes on most 64 bit systems) and
malloc(sizeof(&len))
Allocates only 8 bytes of memory (or whatever pointer size is on your system).
This is probably at least part of the issue.
Related
I am trying a program in c to read a text file that contains array of characters or a string and find the number of occurrences of the substring called "GLROX" and say sequence found when it is found. And the "inputGLORX.txt" contains following string inside it.
GLAAAROBBBBBBXGLROXGLROXGLROXGLROXGLCCCCCCCCCCCCCCROXGGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROX
But i am getting wierd results. It would be great if some expert in C-programming helps me to solve this and thanks in advance.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define NUMBER_OF_STRINGS 40
#define MAX_STRING_SIZE 7
void seqFound()
{
printf("Sequence Found\n");
}
int main()
{
FILE *fp;
char buff[1000];
char strptrArr[NUMBER_OF_STRINGS] [MAX_STRING_SIZE];
const char *search = "GLROX";
fp = fopen("D:/CandC++/inputGLORX.txt", "r");
if(fp==NULL)
printf("It is a null pointer");
while(!feof(fp))
{
//fscanf(fp, "%s", buff);
fgets(buff, 1000,fp);
}
int len = strlen(buff);
printf("length is %d\n",len);
int count = 0;
char *store;
while(store = strstr(buff, search))
{
printf("substring is %s \n",store);
count++;
search++;
}
printf("count is %d\n",count);
while (count!=0) {
seqFound();
count--;
}
return 0;
}
As said in the comment, their are at least 2 problems in the code: your fgets will only fetch the last line (if it fetch one at all ? In any case, this is not what you want), and you are incrementing the search string instead of the buff string.
Something like this should fix most of your problems, as long as no lines in your file are longer than 999 characters. This will not work properly if you use the \n or NULL characters in your search string.
int count = 0;
while (fgets(buff, 1000, fp) != NULL)
{
char *temp = buff;
while ((temp = strstr(temp, search)))
{
printf("%d. %s\n", count + 1, temp);
count++;
temp++;
}
}
Here is a main for testing. I used argv to provide the input.txt and the search string.
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
FILE *fp;
char buff[1000];
char *search;
if (argc < 3)
return (-1);
search = argv[2];
if (search[0] == '\0')
return (-1);
if ((fp = fopen(argv[1], "r")) == NULL)
return (-1);
int count = 0;
while (fgets(buff, 1000, fp) != NULL)
{
char *temp = buff;
while ((temp = strstr(temp, search)))
{
printf("%d. %s\n", count + 1, temp);
count++;
temp++;
}
}
printf("Match found: %d\n", count);
return 0;
}
The way you search in buff is wrong, i.e. this code:
while(store = strstr(buff, search))
{
printf("substring is %s \n",store);
count++;
search++; // <------- ups
}
When you have a hit, you change search, i.e. the string you are looking for. That's not what you want. The search string (aka the needle) shall be the same all the time. Instead you want to move forward in the buffer buff so that you can search in the remainder of the buffer.
That could be something like:
int main()
{
const char* buff = "GLAAAROBBBBBBXGLROXGLROXGLROXGLROXGLCCCCCCCCCCCCCCROXGGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROX";
const char* search = "GLROX";
const char* remBuff = buff; // Pointer to the remainder of buff
// Initialized to be the whole buffer
const char* hit;
int cnt = 0;
while((hit = strstr(remBuff, search))) // Search in the remainder of buff
{
++cnt;
remBuff = hit + 1; // Update the remainder pointer so it points just 1 char
// after the current hit
}
printf("Found substring %d times\n", cnt);
return 0;
}
Output:
Found substring 15 times
I have an archive results.csv and I need to read the first line of this archive and print it out on output.txt. Somehow it's printing random characters after everything and I couldn't figure out what is wrong.
Command: a.c results.csv
First line:
date,home_team,away_team,home_score,away_score,tournament,city,country,neutral
output.txt: date,home_team,away_team,home_score,away_score,tournament,city,country,neutral,(!£,(!£,(!£,(!£,(!£,#,£,(!£,(!£
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct
{
char *line1;
char *line1a;
char *line1b;
char *team1;
char *team2;
char *reason;
char *city;
char *country;
char *neutral_field;
}data;
void open_input(char *argv[], FILE **input)
{
if((*input=fopen(argv[1], "r")) == NULL)
{
printf("%s not found\n", argv[1]);
exit(1);
}
}
void open_output(char *string, FILE **output)
{
if((*output=fopen(string, "w")) == NULL)
{
printf("%s not found\n", string);
exit(1);
}
}
void alloc_data(data *d, int size)
{
d->line1 = (char*)malloc(4*sizeof(char));
d->team1 = (char*)malloc(9*sizeof(char));
d->team2 = (char*)malloc(9*sizeof(char));
d->line1a = (char*)malloc(10*sizeof(char));
d->line1b = (char*)malloc(10*sizeof(char));
d->reason = (char*)malloc(10*sizeof(char));
d->city = (char*)malloc(4*sizeof(char));
d->country = (char*)malloc(7*sizeof(char));
d->neutral_field = (char*)malloc(7*sizeof(char));
}
void store(data *d, FILE *input, FILE **output)
{
fscanf(input, "%s,%s,%s,%s,%s,%s,%s,%s,%s", d[0].line1, d[0].team1, d[0].team2, d[0].line1a, d[0].line1b, d[0].reason, d[0].city, d[0].country, d[0].neutral_field );
fprintf(*output, "%s,%s,%s,%s,%s,%s,%s,%s,%s\n", d[0].line1, d[0].team1, d[0].team2, d[0].line1a, d[0].line1b, d[0].reason, d[0].city, d[0].country, d[0].neutral_field );
}
int main(int argc, char *argv[])
{
FILE *input;
FILE *output;
char *string = "output.txt";
int size = 1000;
open_input(argv, &input);
open_output(string, &output);
data *d;
d = (data*)malloc(size*sizeof(data));
alloc_data(d, size);
store(d, input, &output);
free(d);
return 0;
}
fscanf(input, "%s,%s,%s,%s,%s,%s,%s,%s,%s", d[0].line1, d[0].team1,...
The above code tries to read the whole line in to d[0].line1 which causes buffer overflow. team1 and the rest will contain uninitialized data.
You have to change fscanf as follows:
fscanf(input, "%3[^ ,\n\t],%9[^ ,\n\t],...
Where 3 is 4 - 1, and 4 is the size of d[0].line1
Alternatively you can use strtok
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void store(FILE *input, FILE *output)
{
char buf[500];
while(fgets(buf, sizeof(buf), input))
{
//strip end-of-line from `buf`
if(strlen(buf))
if(buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = 0;
//tokenize with strtok
char *token = strtok(buf, ",");
while(token)
{
fprintf(output, "%s", token);
token = strtok(NULL, ",");
}
fprintf(output, "\n");
}
}
int main(int argc, char *argv[])
{
FILE *input = fopen("input.txt", "r");
FILE *output = fopen("output.txt", "w");
store(input, output);
return 0;
}
With above code you don't need an additional structure.
If you do use a structure for data, you have to be more careful. It seems you are trying to create an array of 1000 data, but the following only creates one oversized pointer, not an array of data
int size = 1000;
data *d;
d = (data*)malloc(size*sizeof(data));
alloc_data(d, size);
Additionally, for each malloc there should be a corresponding free.
Your buffers aren't big enough to hold the terminating NUL byte. scanf stores that NUL byte (overrunning the buffer), but then the object that really owns that byte may overwrite it, so when printf looks for the NUL it doesn't find it until much later in memory.
The buffer overruns are a bigger problem than what you've seen, who knows what objects those NUL bytes you didn't make space for are smashing? And what happens when you read a data file with slightly different header spelling? Suddenly your hard-coded allocations sizes will be even more wrong than they are already.
In the below code, the file test.txt has the following data :
192.168.1.1-90
192.168.2.2-80
The output of this is not as expected.
I expect the output to be
192.168.1.1
90
192.168.2.2
80
Any help would be much appreciated.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
char *result[10][4];
int i=0;
const char s[2] = "-";
char *value,str[128];
fp = fopen("test.txt", "r");
if (fp == NULL)
printf("File doesn't exist\n");
else{
while(!feof(fp)){
if(fgets(str,sizeof(str),fp)){
/* get the first value */
value = strtok(str, s);
result[i][0]=value;
printf("IP : %s\n",result[i][0]); //to be removed after testing
/* get second value */
value = strtok(NULL, s);
result[i][1]=value;
printf("PORT : %s\n",result[i][1]); //to be removed after testing
i++;
}}
for (int k=0;k<2;k++){
for (int j=0;j<2;j++){
printf("\n%s\n",result[k][j]);
}
}
}
return(0);
}
You can try this solution. It uses dynamic memory instead, but does what your after.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 128
void exit_if_null(void *ptr, const char *msg);
int
main(int argc, char const *argv[]) {
FILE *filename;
char buffer[BUFFSIZE];
char *sequence;
char **ipinfo;
int str_size = 10, str_count = 0, i;
filename = fopen("ips.txt", "r");
if (filename == NULL) {
fprintf(stderr, "%s\n", "Error Reading File!");
exit(EXIT_FAILURE);
}
ipinfo = malloc(str_size * sizeof(*ipinfo));
exit_if_null(ipinfo, "Initial Allocation");
while (fgets(buffer, BUFFSIZE, filename) != NULL) {
sequence = strtok(buffer, "-\n");
while (sequence != NULL) {
if (str_size == str_count) {
str_size *= 2;
ipinfo = realloc(ipinfo, str_size * sizeof(*ipinfo));
exit_if_null(ipinfo, "Reallocation");
}
ipinfo[str_count] = malloc(strlen(sequence)+1);
exit_if_null(ipinfo[str_count], "Initial Allocation");
strcpy(ipinfo[str_count], sequence);
str_count++;
sequence = strtok(NULL, "-\n");
}
}
for (i = 0; i < str_count; i++) {
printf("%s\n", ipinfo[i]);
free(ipinfo[i]);
ipinfo[i] = NULL;
}
free(ipinfo);
ipinfo = NULL;
fclose(filename);
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
The key thing to understand is that char *strtok(char *str, const char *delim) internally modifies the string pointed to by str and uses that to store the result. So the returned pointer actually points to somewhere in str.
In your code, the content of str is refreshed each time when you parse a new line in the file, but the address remains the same. So after your while loop, the content of str is the last line of the file, somehow modified by strtok. At this time, result[0][0] and result[1][0] both points to the same address, which equals the beginning of str. So you print the same thing twice in the end.
This is further illustrated in the comments added to your code.
int main()
{
FILE *fp;
char *result[10][4];
int i=0;
const char s[2] = "-";
char *value,str[128];
fp = fopen("test.txt", "r");
if (fp == NULL)
printf("File doesn't exist\n");
else{
while(!feof(fp)){
if(fgets(str,sizeof(str),fp)){
/* get the first value */
value = strtok(str, s);
// ADDED: value now points to somewhere in str
result[i][0]=value;
// ADDED: result[i][0] points to the same address for i = 0 and 1
printf("IP : %s\n",result[i][0]); //to be removed after testing
/* get second value */
value = strtok(NULL, s);
// ADDED: value now points to somewhere in str
result[i][1]=value;
// ADDED: result[i][1] points to the same address for i = 0 and 1
printf("PORT : %s\n",result[i][1]); //to be removed after testing
i++;
}}
// ADDED: now result[0][0]==result[1][0], result[0][1]==result[1][1], you can test that
for (int k=0;k<2;k++){
for (int j=0;j<2;j++){
printf("\n%s\n",result[k][j]);
}
}
}
return(0);
}
To get the expected output, you should copy the string pointed by the pointer returned by strtok to somewhere else each time, rather than just copy the pointer itself.
int main()
{
//FILE *out = fopen("keimeno.txt", "w+");
FILE *in = fopen("keimeno.txt", "r");
int fullbufflen=0 , i;
char buffer[100];
fgets(buffer, 100, in);
int bufflen = strlen(buffer);
char *text;
text =calloc(bufflen,sizeof(char));
char *strcat(text, buffer);
// printf("line of \"keimeno.txt\": %s", buffer);
// printf("size of line \"keimeno.txt\": %i\n\n", bufflen);
fullbufflen = bufflen;
while(fgets(buffer, 100, in)!=NULL)
{
// printf("line of \"keimeno.txt\": %s", buffer);
// printf("size of line \"keimeno.txt\": %i\n\n", bufflen);
text =realloc(text,bufflen*sizeof(char));
char *strcat(text, buffer);
fullbufflen = bufflen + fullbufflen ;
}
for (i = 0;i<fullbufflen;i++)
{
printf("%c\n",text[i]);
}
}
I am trying to copy the full text file (keimeno.txt) into a dynamic memory array, with a buffer of 100 character at most everytime. To test it at the end i tried to prinf the results. And i just cant get it to work. Dont know if there is a problem on the printf at the end, or the whole program is just wrong.
Also the dynamic array is supposed to have 0 size at the beggining, so if someone could tell me how to do that too, it would be welcome.
Thanks in advance.
There are a few issues:
char *strcat(text, buffer);
This is not how you call a function. This is a function declaration, and an incorrect one at that since it doesn't define the types of the arguments.
To call strcat, just do this:
strcat(text, buffer);
Next, you're not allocating enough space for your buffers:
text =calloc(bufflen,sizeof(char));
You need to add space for the null bytes that terminates the string:
text =calloc(bufflen + 1,sizeof(char));
Similarly here:
text =realloc(text,bufflen*sizeof(char));
This only reallocates a total of bufflen bytes. It does not add bufflen bytes to what was already allocated, and bufflen is unchanged from when it was first set outside of the while loop. Do this instead:
bufflen = strlen(buffer);
text =realloc(text,bufflen+fullbufflen+1);
This gives you enough space for the current length, the additional buffer, and the null byte.
Finally, make sure you fclose(in) and free(text) at the end to clean up your resources, and be sure to check the return value of fopen to ensure that the file opened successfully, and realloc/calloc to ensure that your allocations worked.
After the above changes, you code should look like this:
int main(void)
{
//FILE *out = fopen("keimeno.txt", "w+");
FILE *in = fopen("keimeno.txt", "r");
if (in == NULL) {
perror("open failed");
exit(1);
}
int fullbufflen=0 , i;
char buffer[100];
fgets(buffer, 100, in);
int bufflen = strlen(buffer);
char *text;
text =calloc(bufflen+1,sizeof(char));
if (text == NULL) {
perror("calloc failed");
exit(1);
}
strcat(text, buffer);
// printf("line of \"keimeno.txt\": %s", buffer);
// printf("size of line \"keimeno.txt\": %i\n\n", bufflen);
fullbufflen = bufflen;
while(fgets(buffer, 100, in)!=NULL)
{
// printf("line of \"keimeno.txt\": %s", buffer);
// printf("size of line \"keimeno.txt\": %i\n\n", bufflen);
bufflen = strlen(buffer);
text =realloc(text,bufflen+fullbufflen+1);
if (text == NULL) {
perror("realloc failed");
exit(1);
}
strcat(text, buffer);
fullbufflen = bufflen + fullbufflen ;
}
fclose(in);
for (i = 0;i<fullbufflen;i++)
{
printf("%c\n",text[i]);
}
free(text);
}
Here is one possible solution:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#define ERR (-1)
#define GROW 100
static void die ( const char * msg ) { perror(msg); exit(1); }
int main ( void ) {
char * filename = "in.txt";
size_t buffSize = 0;
size_t buffUsed = 0;
ssize_t bytesRead = 0;
char * buffer = NULL;
char * tmp;
int fd;
fd = open(filename, O_RDONLY, 0);
if (fd == ERR) die("open");
do {
buffUsed += (size_t)bytesRead;
if (buffUsed == buffSize) {
tmp = realloc(buffer, buffSize += GROW);
if (tmp == NULL) die("realloc");
buffer = tmp;
}
bytesRead = read(fd, buffer + buffUsed, buffSize - buffUsed);
if (bytesRead == ERR) die("read");
} while (bytesRead > 0);
if (write(STDOUT_FILENO, buffer, buffUsed) == ERR) die("write");
free(buffer);
if (close(fd) == ERR) die("close");
return 0;
}
Like the original, the input filename is hard-coded which sub-optimal...
in my program, I provide a directory which contains text files. Each of the text files contain a few hundred lines in the following format
Username,Password,BloodType,Domain,Number
I then create a thread for each file in the directory which will merge-sort(by number) these lines into the array char* text_lines[6000];
I can't figure out why I'm getting a segmentation fault because I'm getting different output on every run.
Heres my code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
void store_line(char* line);
void* my_merge_sort(void* file);
char** text_lines;
int main(int argc, char* argv[])
{
if(argc != 2)
{
fprintf(stderr, "usage: ./coolsort <directory>\n");
}
else
{
text_lines = malloc(6000 * sizeof(char*));
DIR* the_directory;
int filecount = 0;
struct dirent* directory_files[50];
if((the_directory = opendir(argv[1])) != NULL)
{
//make a list of the files in the directory
while((directory_files[filecount++] = readdir(the_directory))) ;
filecount--;
//<<<DEBUGGING INFO>
int i;
fprintf(stderr,"there are %i files in %s:\n", filecount, argv[1]);
for(i = 0; i < filecount; i++)
{
fprintf(stderr, "%s\n",directory_files[i]->d_name);
}
char cwd[512];
chdir(argv[1]);
getcwd(cwd, sizeof(cwd));
fprintf(stderr, "the CWD is: %s\n", cwd);
//<DEBUGGING INFO>>>
//lets start some threads
pthread_t threads[filecount-2];
int x = 0;
for(i = 0; i < (filecount); i++ )
{
if (!strcmp (directory_files[i]->d_name, "."))
continue;
if (!strcmp (directory_files[i]->d_name, ".."))
continue;
pthread_create(&threads[x++], NULL, my_merge_sort, (void*)directory_files[i]->d_name);
}
//do stuff here
//
}
else
{
fprintf(stderr, "Failed to open directory: %s\n", argv[1]);
}
}
}
void* my_merge_sort(void* file)
{
fprintf(stderr, "We got into the function!\n");
FILE* fp = fopen(file, "r");
char* buffer;
char* line;
char delim[2] = "\n";
int numbytes;
//minimize I/O's by reading the entire file into memory;
fseek(fp, 0L, SEEK_END);
numbytes = ftell(fp);
fseek(fp, 0L, SEEK_SET);
buffer = (char*)calloc(numbytes, sizeof(char));
fread(buffer, sizeof(char), numbytes, fp);
fclose(fp);
//now read the buffer by '\n' delimiters
line = strtok(buffer, delim);
fprintf(stderr, "Heres the while loop\n");
while(line != NULL)
{
store_line(line);
line = strtok(buffer, NULL);
}
free(buffer);
}
void store_line(char* line)
{
//extract the ID.no, which is the fifth comma-seperated-token.
char delim[] = ",";
char* buff;
int id;
int i;
strtok(line, delim);
for(i = 0; i < 3; i++)
{
strtok(line, NULL);
}
buff = strtok(line, NULL);
id = atoi(buff);
//copy the line to text_lines[id]
memcpy(text_lines[id], line, strlen(line));
}
edit: I checked to make sure that it would fit into the initial array, and found that the highest ID is only 3000;
You use of strtok() is wrong:
line = strtok(buffer, NULL);
should be
line = strtok(NULL, delim);
Another mistakes should be fixed similarly.
The elements of text_lines are uninitialized:
text_lines = malloc(6000 * sizeof(char*));
this allocated 6000 pointers to char, but none of these pointers are initialized.