I'm having a problem I can't tell what to do. I have this task that asks me to take the words from a file (let's say input.txt) and write them all in another file (let's say output.txt) in the reverse order. The fun part is that when I execute my program (I have a VM of Xubuntu given to me from my University) it's impossible to double click the output.txt file 'cause something's wrong: I'll try to translate it:
"Byte sequence invalid in the conversion's input"
The fun part is that if I do "gedit output.txt" I do see those words all well written how they should be, so I'd say my program "works but corrupts the file". What can be the theoreticals reasons behind this? And if you wanna help me out pointing them, here's a link to my code [EDIT, it seems I can't post the pastebin link. Here's the part that involves the output file]:
`char *t=malloc(sizeof(char)*1025), *tmp;
t=fgets(t,1024,fp);
while(t!=NULL){
tmp=strtok(t, " ");
while(tmp!=NULL){
tmp=strrev(tmp);
fprintf(fo, " %s", tmp);
tmp=strtok(NULL, " ");
}
t=fgets(t,1024,fp);
}`
I hope I didn't break any rule 'cause I'm still new to this site, thanks all!
It's seem there is not a problem with your code itself.
Can you test this and say if your problem is here again ?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *strrev(char *str)
{
int i = 0;
int j = strlen(str) - 1;
while (i < j) {
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
++i;
--j;
}
return (str);
}
#define BUFFER_LEN 1024
int main(int argc, char* argv[])
{
char line[BUFFER_LEN + 1];
FILE *fp = NULL;
FILE *fo = NULL;
if (argc != 3 && argc != 4) {
fprintf(stderr, "Devi usare 2 o 3 argomenti grz\n");
return -1;
}
if (!(fp = fopen(argv[1],"r"))) { //argv1=input.txt
fprintf(stderr, "Devi \n");
return -1;
}
if (!(fo = fopen(argv[2], (argc == 4 && strcmp(argv[3],"a")) ? "a" : "w"))) {
fprintf(stderr, " 3 argomenti grz\n");
return -1;
}
while(fgets(line, BUFFER_LEN, fp)) {
for (char *word = strtok(line, " "); word; word = strtok(NULL, " ")) {
fprintf(fo, "%s ", strrev(word));
}
}
fclose(fp);
fclose(fo);
return 0;
}
Can you compile & run this code and say if "mousepad" is still losing himself ?
int main(int argc, char* argv[])
{
FILE *fo = NULL;
if (argc != 3 && argc != 4) {
fprintf(stderr, "Devi usare 2 o 3 argomenti grz\n");
return -1;
}
if (!(fo = fopen(argv[2], "w"))) {
fprintf(stderr, " 3 argomenti grz\n");
return -1;
}
fprintf(fo, "test");
fclose(fo);
return 0;
}
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
Hello and good evening,
So i'm writing a program in C, that will accept a file.txt as an input and read the text. The program should read the text file, find the longest and shortest word within the file, and print them out when it reaches the end.
I'm REALLY close but i'm getting a seg fault and, not only do I not know why, but i'm at a loss as to how to fix it.
Here's the code:
#include <stdio.h>
#include <string.h>
FILE *fp;
char str[60];
char *largest;
char *smallest;
char *word;
int i, j;
int main (int argc, char **argv) {
// check that there are only two arguments
if (argc == 2) {
fp = fopen(argv[1], "r");
}
// if not throw this error
else {
perror("Argument error.");
return (-1);
}
// check if the file exists
if (fp == NULL) {
perror("Error opening file.");
return (-1);
}
// set largest to first string and smallest to second
largest = strcpy(largest, strtok(str, " "));
smallest = strcpy(smallest, strtok(NULL, " "));
word = strcpy(word, strtok(str, " "));
// while we get lines of the file
while (fgets (str, 60, fp) != NULL) {
// while the token string isn't empty
while (word != NULL) {
if (strlen(largest) > strlen(word)) {
strcpy(word, largest);
}
if (strlen(smallest) < strlen(word)) {
strcpy(word, smallest);
}
}
}
printf("The largest word in the file is: %s", largest);
printf("The smallest word in the file is: %s", smallest);
fclose(fp);
return 0;
}
I'm pretty sure it's the second while loop...I don't want to use it anyway, but i've been hacking at this for so long it's all my logic can think of.
Any help would be appreciated. This IS homework, though only a small part of it, and i'm not asking for helping solving the entire problem.
Also, there is a Makefile involved...I don't think it's important post but feel free to ask me and i'll update.
As I built this I can confirm that the file is able to read and I can print, put, and do all kinds of cool things. It only broke when I tried to implement my logic for longest/shortest word.
Thanks!
There are some problems with your logic. Try the below code
Few assumptions I made are,
Maximum word length is 20 characters. You can change it by MAX_WORD_LENGTH macro.
Words in file are space separated
Max line length is 60 characters
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_WORD_LENGTH 20
int main (int argc, char **argv)
{
FILE *fp;
char str[60];
char *largest = (char*) malloc (MAX_WORD_LENGTH);
char *smallest = (char*) malloc (MAX_WORD_LENGTH);
int smallest_len = MAX_WORD_LENGTH, largest_len = 0;
if (argc == 2)
{
fp = fopen(argv[1], "r");
}
else
{
printf("Argument error.");
return (-1);
}
if (fp == NULL)
{
printf("Error opening file.");
return (-1);
}
while (fgets (str, 60, fp) != NULL)
{
char *temp = strtok(str, " ");
while (temp != NULL)
{
if (strlen(temp) > largest_len)
{
strcpy(largest, temp);
largest_len = strlen(largest);
}
if (strlen(temp) < smallest_len)
{
strcpy(smallest, temp);
smallest_len = strlen(smallest);
}
temp = strtok(NULL, " ");
}
}
printf("The largest word in the file is: %s\n", largest);
printf("The smallest word in the file is: %s\n", smallest);
fclose(fp);
return 0;
}
Adopt it for your needs with argv[2]
and enjoy
#include <stdio.h>
#include <string.h>
int main() {
const int max_word_length = 60;
char longest[max_word_length];
char shortest[max_word_length];
char current[max_word_length];
size_t longest_length = 0;
size_t shortest_length = max_word_length;
size_t current_length = 0;
freopen("input", "r", stdin);
freopen("output", "w", stdout);
while (scanf("%s", current) > 0) {
current_length = strlen(current);
if ( current_length > longest_length) {
longest_length = current_length;
strcpy(longest, current);
}
if (current_length < shortest_length) {
shortest_length = current_length;
strcpy(shortest, current);
}
}
printf("%s %s", shortest, longest);
return 0;
}
So I just ran this online and it looks like the seg fault is caused by the line
largest = strcpy(largest, strtok(str, " "));
This is because largest is the destination of the string copy in the call
strcpy(largest, strtok(str, " "));
but it's a pointer that points to nothing. It should be declared as an actual array like this:
char largest[60];
Also, you shouldn't be calling strtok on a str when it hasn't been initialized to anything. It's not even a proper string so there's no way strtok is going to do anything useful at that point.
So the title I know is a little misleading with the contents, but my question is: with the code provided here, when I run ./tstats input1.txt input2.txt the output is as follows
5 1 21 input1.txt
2 1 11 input1.txt
So it's obvious that the information from each file is going through but the names of the files aren't. Any idea as to why this is happening? Some small mistake I'm looking over?
Secondly, how would I tally all of the wcount results so that I have:
7 2 32 total
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
enum state
{
START,
WORD,
DELIM,
};
FILE*
input_from_args(int argc, char *argv[])
{
if (argc == 1)
{
return stdin;
}
else
{
return fopen(argv[1], "r");
}
}
char* get_filename_from_args(int argc, char* argv[])
{
int i;
static char stdin_name[] = "-";
if (argc == 1)
{
return stdin_name;
}
else
{
for (i = 1; i < argc; i++)
{
return argv[i];
}
return argv[i];
}
}
void
wcount(FILE *src, FILE *dest, char* src_filename)
{
int ch, wc, lc, cc;
enum state cstate;
wc = lc = cc = 0;
cstate = START;
while ((ch = fgetc(src)) != EOF){
cc++;
switch (cstate) {
case START:
if (isspace(ch)) {
cstate = DELIM;
if (ch == '\n') {
lc++;
}
}
else {
cstate = WORD;
wc++;
}
break;
case DELIM:
if (ch == '\n') {
lc++;
}
else if (!isspace(ch)) {
cstate = WORD;
wc++;
}
break;
case WORD:
if (isspace(ch)) {
cstate = DELIM;
if (ch == '\n') {
lc++;
}
}
break;
}
}
fprintf(dest, "%4d\t%4d\t%4d\t%10s\n", wc, lc, cc, src_filename);
}
int
main(int argc, char* argv[])
{
int i;
FILE *src = input_from_args(argc, argv);
FILE *dest = stdout;
for (i = 1; i < argc; i++)
{
if ((src = fopen(argv[i], "r")) == NULL)
{
fprintf(stderr, "%s: unable to open %s\n", argv[0], argv[i]);
}
wcount(src, dest, get_filename_from_args(argc, argv));
fclose(src);
}
return EXIT_SUCCESS;
}
get_filename_from_args doesn't do what you think it does. Get rid of it entirely and just use argv[i] again at the call site.
regarding this sub question:
Secondly, how would I tally all of the wcount results so that I have:
7 2 32 total
add three global int variables
Then when each value is available, add it to the appropriate global variables.
Then, in the end, printf the contents of those global variables
This line:
'wcount(src, dest, get_filename_from_args(argc, argv));'
is not stepping through the arguments contained in argv.
Suggest:
'wcount(src, dest, argv[i]);'
and eliminating the function:
'char* get_filename_from_args(int argc, char* argv[])'
I am getting a segmentation fault when I call my getField(char *line, int field) function in my while loop and I'm not sure why. I'm trying to pass a line to the function and a column number so that I can grab specific columns from each line in a csv file and print them to the screen. Thanks for input.
void getField(char *line, int field);
int main(int argc, char *argv[]) {
if(argc < 3) {
fprintf(stderr, "Too few arguments \"%s\".\n", argv[0]);
}
if(atoi(argv[1]) < 1) {
fprintf(stderr, "First argument must be >= 1 \"%s\".\n", argv[1]);
}
FILE *fp = fopen(argv[2], "r");
if(fp == NULL)
fprintf(stderr, "Cannot open file %s\n", argv[0]);
char buf[80];
while(fgets(buf, 80, fp) != NULL) {
getField(buf, atoi(argv[1]); // seg fault is happening here
}
return 0;
}
void getField(char *line, int field) {
printf("here2");
//char *ln = line;
int column = field - 1;
int idx = 0;
while(column) {
//printf("here");
if(line[idx] == ',') field--;
idx++;
}
for(int j = idx; ; ++j) {
if(line[j] == ',') break;
printf("%s", line[j]);
}
printf("\n");
printf("%d", idx);
}
One obvious error is that you have an infinite loop here, and you will eventually access illegal memory.
while(column) {
//printf("here");
if(line[idx] == ',') field--;
idx++;
}
You are not modifying column at all, so your loop cannot possibly end.
column will not update itself when you update field, so you will have to update it if you want it to update.
while(column) {
//printf("here");
if(line[idx] == ',') field--;
idx++;
column = field - 1;
}
Note on debugging segfaults using printf.
The function printf prints to stdout and stdout likes to buffer output. This means that sometimes if you try to find a segfault by moving a print statement down your code until it fails to print, you will misunderstand where the segfault it happening. In particular, a printf line that appears before the line that actually contains the segfault may not print even if you might expect it to.
If you want to use this strategy (instead of gdb), you can force it to print by using fflush(stdout); immediately after your debugging printf.
while(column) {
//printf("here");
if(line[idx] == ',') column--; // Changed field-- to column--
idx++;
}
In following line:
printf("%s", line[j]);
you are using the %s format specifier but you are passing a char as argument.
You probably want this (%c format specifier fot printing a char):
printf("%c", line[j]);
You are accessing out of bounds of the array in the function getField because the while loop never exits. This invokes undefined behaviour and most likely program crash due to segfault which is what is happening in your case. I suggest the following changes to your program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void getField(char *line, int field);
int main(int argc, char *argv[]) {
if(argc < 3) {
fprintf(stderr, "Too few arguments \"%s\".\n", argv[0]);
return 1; // end the program
}
if(atoi(argv[1]) < 1) {
fprintf(stderr, "First argument must be >= 1 \"%s\".\n", argv[1]);
return 1; // end the program
}
FILE *fp = fopen(argv[2], "r");
if(fp == NULL) {
fprintf(stderr, "Cannot open file %s\n", argv[0]);
return 1; // end the program
}
char buf[80];
while(fgets(buf, 80, fp) != NULL) {
getField(buf, atoi(argv[1])); // seg fault is happening here
}
return 0;
}
void getField(char *line, int field) {
int len = strlen(line);
char temp[len + 1];
strcpy(temp, line);
int count = 0;
char ch = ',';
char *p = temp;
char *q = NULL;
while(count < field - 1) {
q = strchr(p, ch);
if(q == NULL) {
printf("error in the value of field\n");
return;
}
count++;
p = q + 1;
}
q = strchr(p, ch);
if(q != NULL)
*q = '\0';
else
temp[len-1] = '\0';
printf("%s\n", p);
}
I just got a semi function head program running and I need help making it into a tail program where it will display x number of lines at the end of the file. Here is my head code.
I'm having trouble thinking of how to get the counter to read the entire file then start at the bottom and show the last lines of the file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1024
int numLines = 0;
int linecount = 0;
FILE *src = NULL;
char ch[MAX];
void GetArgs (int argc, char **argv){
if(argc != 4 || argc != 2) {
printf("Error not enough arguments to continue \n", argv[0]);
exit(-1);
}// end if argc doenst = 4 or 2
if(argc == 2){
src = fopen( argv[1], "r:");
numLines=10;
}// end argc = 2
if(argc == 4){
if (strcmp (argv[1], "-n") !=0 ){
numLines = atoi (argv[2]);
src = fopen (argv[3], "r");
if ( src == NULL){
fputs ( "Can't open input file." , stdout);
exit (-1);
}
while (NULL != fgets(ch, MAX, src)){
linecount++;
fputs(ch, stdout);
if (linecount == numLines){
break;
}
}
}//end of nested if
else if (strcmp (argv[2], "-n") !=0 ){
numLines = atoi (argv[3]);
src = fopen (argv[1], "r");
if ( src == NULL){
fputs ( "Can't open input file." , stdout);
exit (-1);
}
while (NULL != fgets(ch,MAX, src)){
linecount++;
fputs(ch, stdout);
if (linecount == numLines){
break;
}
}
}//end of else
}//end if argc == 4
}// end GetArgs
int main(int argc, char **argv){
GetArgs(argc, argv);
fclose( src );
}
You can keep a counter to pass through the whole file and count the total number of lines (Only call fgets to read one line at a time). Suppose N is the total number of lines and n is the number of last lines to be shown on the screen. Then start again at the beginning of the file pass through N - n lines without showing them on the screen (i.e. dont call fputs), after that call fputs for n number of times.
I used your variables and style. If I understand, you want to printout last [X] lines from file. [X] - parameter from CLI
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX 1024
FILE *src = NULL;
FILE *src_end = NULL;
int linecount = 0;
char ch[MAX];
int main(int arc, char **argv) {
int i = 0;
int letter = 0;
if (arc != 4) {
puts("Wrong parameters");
return 1;
}
do {
src = fopen(argv[1], "r");
if (src == NULL) {
puts("Can't open input file.");
break;
}
if (0 != strcmp(argv[2], "-n")) {
puts("Wrong 2nd parametr");
break;
}
sscanf(argv[3], "%u", &linecount);
printf("Printout last %u lines, from file:%s\n", linecount,
argv[1]);
src = fopen(argv[1], "r");
if (src == NULL) {
fputs("Can't open input file.", stdout);
return 1;
}
for (i = 2; linecount; i++) {
fseek(src, -i, SEEK_END);
letter = fgetc(src);
if (letter == 0x0a) { // 0x0a == "\n"
fgets(ch, MAX, src);
fputs(ch, stdout);
linecount--;
}
}
} while (0);
fclose(src);
return 1;
}