Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
This code does reverse and put result in file, but not fully correct.
Like, some issues with detecting line breaker or sth. Here's an example:
Source:
This is a line.
This is another line.
Quick brown fox jumps over a lazy dog!
Result:
(blank line)
.enil a si sihT
.enil rehtona si sihT!god yzal a revo spmuj xof nworb kciuQ
#include <stdio.h>
#include <string.h>
char *reverse (char *str)
{
char *begin, *end, c;
if (!str || !(*str))
return NULL;
for (begin=str, end=str+strlen(str)-1; begin<end; begin++, end--)
{
c=*begin;
*begin=*end;
*end=c;
}
begin=str+strlen(str)+1; *begin='\0'; //??
return str;
}
void main(void)
{
char line[1000];
FILE *fsrc, *frslt;
fsrc=fopen("source.txt", "r");
if (fsrc==NULL) return;
frslt=fopen("result.txt", "w");
while (!feof(fsrc))
{
fgets (line, 1000, fsrc);
fputs (reverse(line), frslt);
}
fclose(fsrc);
fclose(frslt);
}
A couple of comments/nitpicks, which may or may not solve your problem :)
if (!str || !(*str))
return NULL;
Don't do that. Don't return NULL on empty strings, fputs() will barf. In my experience, it's better to a) assert that the str pointer is non-null, b) return the empty string.
begin=str+strlen(str)+1; *begin='\0'; //??
There should be no need to terminate the string, since it's already terminated.
void main(void)
Nah, main() returns an int.
while (!feof(fsrc))
This won't work. You need to do some IO before you can test for feof()/ferror(). IMHO it's better to simply loop on fgets().
while (fgets(line, sizeof line, fsrc) {
...
}
It may be a good idea to drop the input and output files, and simply read from stdin and write to stdout, at least while testing. The functionality you're trying to implement is already available in a UNIX shell (man rev). Using stdin/stdout makes it easier to test and compare results with the results from rev.
Also, keep in mind that fgets() won't remove the \n from the string. input like "foo\n" becomes "\noof", which is probably not what you want.
Here's a snippet which illustrates my comments in code. It doesn't solve all problems, but should be sufficient to get you going.
#include <stdio.h>
#include <string.h>
#include <assert.h>
void reverse(char *str)
{
char *begin, *end, c;
size_t n;
assert(str != NULL);
n = strlen(str);
if (n == 0)
return;
for (begin = str, end = str + n - 1; begin < end; begin++, end--) {
c = *begin;
*begin = *end;
*end = c;
}
}
int main(void)
{
char line[1000];
while (fgets(line, sizeof line, stdin)) {
reverse(line);
fputs(line, stdout);
}
}
HTH
Related
I'm trying to make a simple program where you put some text in it and it write back what you just wrote.
For example if I write "Hello World", the program should write me back "Hello World"
How I think it should work is like that :
loop to check if the current character is '\0'
if not print the current character and reallocate 1 more byte of memory
else stop the loop
So it's looks like an easy thing to do but my attempt is not working correctly, for example if you put only a few characters it is going to write you back with no problem but with longer string.. it is not working at all.
I know it is possible using fgets(), but I would like to understand why my version with scanf() isn't working.
(my code)
#include <stdio.h>
#include <stdlib.h>
int main(void){
int mem = 2;
char * str = malloc(mem);
scanf("%s", str);
while (*str != '\0') {
printf("%c", *str);
realloc(str, mem++);
str++;
}
free(str);
return 0;
}
edit : I was thinking that I only did a small mistake but, after reading the comments it looks like there is a lot of things that I did wrong in this tiny program. I'm going make sure that I better understand how C work and retry to do this program later. Thanks for the help!
Your program could be much more simple
#include <stdio.h>
int main() {
char c;
while( scanf("%c", &c) == 1 ) {
printf("%c", c);
}
return 0;
}
If you're going to use scanf for this, you shouldn't use "%s". (You should never use "%s" without a field width, since this will potentially overflow a buffer. Using "%s" is no better that gets().) If you are going to use a variant of "%s", you need to understand that it will ignore whitespace. The following does almost what you want, except for the whitespace issue. If you want to handle whitespace with precision, you cannot use "%s".
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
void * xrealloc(void *buf, size_t num, size_t siz, void *endvp);
int
main(void)
{
size_t cap = 2;
char *end = NULL;
char *str = xrealloc(NULL, cap, sizeof *str, &end);
/*
* Read 1 char at a time, discarding whitespace. This should
* be done with getchar(). If using scanf, a single char
* should be read with "%c". We use "%1s" here only
* because the question is specifically about `%s`.
* Note that %1s will allow scanf to write up to 2 characters into
* *end, so we need to ensure there is space for the terminator.
*/
while( 1 == scanf("%1s", end++) ){
while( end > str + cap - 2 ){
str = xrealloc(str, cap *= 2, sizeof *str, &end);
}
}
fputs(str, stdout);
free(str);
return 0;
}
void *
xrealloc(void *buf, size_t num, size_t siz, void *endvp)
{
char **endp = endvp;
char *b = buf;
ptrdiff_t offset = b && endp && *endp ? *endp - b : 0;
b = realloc(b, num * siz);
if( b == NULL ){
perror("realloc");
exit(EXIT_FAILURE);
}
if( endp != NULL ){
*endp = b + offset;
}
return b;
}
Reading functions' manuals and searching for similar questions is a great method to get things clearer, and undestand the problem you are facing better :)
Try looking at this question: Reading input of unknown length, and particularly at this answer that uses scanf: scanf answer (I did not verify if that works, but it teaches you another method you can use).
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I run the program with this command:
./word_search oi < text.txt
and got segmentation fault when running it.
This program is aiming to find where the word (giving as command line arg) exists in a file and print out those lines.
#include <stdio.h>
#include "substring.c"
int main(int argc, char ** argv) {
if(argc == 2) {
char *str;
while(fgets(str, 100, stdin)) {
if(substring(str, argv[1]) != -1) {
printf("Found: %s", str);
}
}
}
return 0;
}
If I change char *str into char str[100] then it works pretty good. Could anyone please tell me why?
The contents in substring.c:
#include <stdio.h>
#include <string.h>
int substring(const char *line, const char *substr) {
int i, j;
int result;
for(i = 0; i <= strlen(line)-strlen(substr); i++) {
result = 0;
if(line[i] == substr[0]) {
int c = i;
for(j = 0; j < strlen(substr); j++) {
if (line[c] != substr[j]) {
result = -1;
}
c++;
}
if(result != -1)
return i;
}
}
return -1;
}
The contents in test.txt are just several lines of meaningless characters.
char *str is an unitialized pointer, it cannot hold the string you are trying to copy into it, either allocate memory to it:
#include <stdlib.h>
#define SIZE 100
char *str = malloc(SIZE); //char has the size of 1 across platforms
Or simply declare it with the size you need:
char str[SIZE];
Pass the size of str to fgets
while(fgets(str, SIZE, stdin))
Of fgets:
Your container will be null terminated, it can only hold a string of SIZE - 1 characters.
All characters above SIZE - 1, including '\n' will remain unread and therefore in the buffer, you might need to clear it.
I suggest you take some time to learn basic C. Especially read about pointers, they are bit hard to get right at first.
In your example, str is a pointer to an undefined memory location.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm working on the following pthread program that finds the number of substrings in string2 that are in string1:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#define NUM_THREADS 4
#define MAX 1024
int n1,n2,i;
char *s1,*s2;
FILE *fp;
char *substring(char *string, int position, int length);
void *occurrence();
int readf(FILE *fp)
{
if((fp=fopen("strings.txt", "r"))==NULL){
printf("ERROR: can't open strings.txt!\n");
return 0;
}
s1=(char *)malloc(sizeof(char)*MAX);
if(s1==NULL){
printf("ERROR: Out of memory!\n");
return -1;
}
s2=(char *)malloc(sizeof(char)*MAX);
if(s1==NULL){
printf("ERROR: Out of memory\n");
return -1;
}
/*read s1 s2 from the file*/
s1=fgets(s1, MAX, fp);
s2=fgets(s2, MAX, fp);
n1=strlen(s1); /*length of s1*/
n2=strlen(s2)-1; /*length of s2*/
if(s1==NULL || s2==NULL || n1<n2) /*when error exit*/
return -1;
return 0;
}
int main(void)
{
pthread_t tid;
pthread_create(&tid, NULL, occurrence, NULL);
pthread_join(tid, NULL);
exit(0);
}
char *substring(char *string, int position, int length)
{
char *pointer;
int c;
pointer = malloc(length+1);
if (pointer == NULL)
{
printf("Unable to allocate memory.\n");
exit(1);
}
for (c = 0 ; c < length ; c++)
{
*(pointer+c) = *(string+position-1);
string++;
}
*(pointer+c) = '\0';
return pointer;
}
void* occurrence()
{
char *string1;
char *string2;
char *new_str;
int counter=0;
readf(fp);
string1 = s1;
string2 = s2;
new_str = malloc(200);
for(i=1;i<=strlen(string1);i++)
{
new_str = substring(string1,i,strlen(string2));
if(strcmp(new_str, string2)==0)
{
counter++;
}
}
printf("The number of substrings is: %d \n",counter);
return 0;
}
When i compile it on codeblocks, it prints the correct number of substrings. However, when I compile it on the Linux kernel, it always prints 1 as the number of substrings, even though there's more than one. For example, a strings.txt file that has abdeabjhab in the first line and ab in the 2nd line should print 3, since there's 3 instances of ab in the first line. My Linux kernel prints 1. Is there a specific way I'm supposed to compile it for it to print the right value? I'm current using gcc -pthread substring.c -o substrings to compile and ./substrings to execute it.
There are several issues here.
First the signature for occurrence is wrong; the thread function should take a void* as argument and return a void* as required by the pthread_create API. So it should be:
void *occurrence(void*);
and
void *occurrence(void arg*) {
...
return NULL;
}
There are several other questionable things in your code.
You are passing the global variable fp to readf() function. Why do you need to pass a global variable?
You are reading only the first two lines. What if the file contains many more lines?
Why do you have s1 and s2 as global? You could easily rewrite it to pass from readf back to occurrence. Or occurrence could pass varibles that readf writes into.
You don't close the file with fclose.
You create just one thread to do the work and the main thread just waits for it. So there's no real need for threads here. You might as well let the main thread do the work and not bother with threads.
Why do you subtract here?: n2=strlen(s2)-1; /*length of s2*/.
What if the length of s1 and s2 are the same? Is "abc" not a substring of "abc"?
Your actual of problem of getting incorrect substring count is probably because fgets() reads in the newline character and thus the substring match fails.
To remove newlines, you can do in your readf function after reading s1 and s2:
char *p = strchr(s1, '\n');
if (p) *p = 0;
p = strchr(s2, '\n');
if (p) *p = 0;
This should fix the immediate problem. But there's a lot you could improve.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I wrote code to reverse a sentence that the user inputs, but when I run this code and write a sentence, this code prints meaningless figures instead of reverse version of my sentence. I need helping locating the error
#include <stdio.h>
#include <string.h>
void reverser(char*);
int readmassage(char[], int);
int main()
{
char mysentence[30];
readmassage(mysentence, 30);
reverser(mysentence);
printf("%s", mysentence);
system("pause");
return 0;
}
void reverser(char *massage)
{
char temp,*p;
p = massage + strlen(massage)-1;
while (p > massage) {
temp = *massage;
*massage = *p;
*p-- = temp;
}
}
int readmassage(char massage[], int lenght)
{
int ch, i = 0;
while (ch = getchar() != '\n') {
if (lenght > i)
massage[i++] = ch;
}
massage[i] = '\0';
return i;
}
Your problem is here:
temp = *massage;
*massage = *p;
*p-- = temp;
massage always points to the first character in your string here. So you keep overwriting the first character, and then writing the new first character to the last character on the next go round. The effect is that you essentially rotate the string by one character instead of reversing it. If you change *massage = *p; to *massage++ = *p; (or create a new incrementing pointer variable to correspond to p which you initialize to massage), it'll probably work.
What I'm saying is that your "start of the string" pointer needs to be... massaged. ba dum chshhhh
EDIT: And you also need to change this, in readmessage:
while (ch = getchar() != '\n')
to:
while ((ch = getchar()) != '\n')
Otherwise, rather than the input character, you're actually setting ch to 0 or 1, depending on whether getchar() is returning '\n' or not. This is because due to the order of operations, != actually gets executed before =, and != gives you 1 if the expression is true and 0 if it is false. This 0 or 1 then gets stored in ch by the = operator.
You could also just replace all of readmessage with fgets, as it's included in the standard library and meant for exactly this sort of thing (unless reimplementing it was part of your assignment, of course).
EDIT:
Adding explanation. There are some issues with your code, few major, few not that serious
Don't use void main(). It's not the best thing to use.
Indenting your code will make it easier to read
Let's look at the readmassage function.
You are assigning the result of getchar() to an int. That's not right. it should be a char
here's a version of your code with minor fixes
#include <stdio.h>
#include <string.h>
void reverser(char*);
int readmassage(char[], int);
void main()
{
char mysentence[30];
readmassage(mysentence, 30);
printf("Input: %s", mysentence);
reverser(mysentence);
printf("Output: %s", mysentence);
system("pause");
return 0;
}
void reverser(char*massage)
{
char temp,*p;
p = massage + strlen(massage)-1;
while (p > massage) {
temp = *massage;
*massage = *p;
*p-- = temp;
}}
int readmassage(char massage[], int lenght)
{
char ch;
int i = 0;
while (ch != '\n')
{
ch = getchar();
printf("Here\n");
if (lenght > i)
{
massage[i++] = ch;
printf("%c\n", massage[i]);
}
}
massage[i] = '\0';
return i;
}
When you try this you will find that the input string gets read fine, just be sure to not to hi Enter after every character and instead type the full string out as \n is a valid character that can be in the stream and will terminate the loop the next iteration.
This is why you should use a char array reading function like fgets.
Once you get here you can see that the reverser is just following a slightly flawed reversing logic.
grammatical errors aside, fixing this you can get
here you go
#include <stdio.h>
#include <string.h>
void reverser(char* message)
{
int start, end;
start = 0;
end = strlen(message) - 1;
char temp;
while (start < end) {
temp = message[start];
message[start] = message[end];
message[end] = temp;
start++;
end--;
}
}
void readmessage(char message[], int length)
{
fgets(message, length , stdin);
}
int main()
{
char mysentence[30];
readmessage(mysentence, 30);
printf("Read the string\n");
reverser(mysentence);
printf("%s\n", mysentence);
return 0;
}
please debugg to find out the reason sometimes.. It will help you..
The problem is when you call readmassage(mysentence, 30) inside the function you have the string input.
When the flow comes back to the method the value is no more there as you had passed mysentence by value..
And you send null to reverse()..
Pass by reference will work..
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 6 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Improve this question
So my program takes a file as input and parses out spaces. Tokens are saved into an array. I have a function to print out the contents of the array to test if the parser works. The code compiles with gcc -o filename filename.c . But when I run the program and give it a filepath, I get a pop up window indicating filename.exe has stopped working : A problem caused the program to stop working correctly. Windows will close the program and notify you if a solution is available.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
char file_name[100];
char *token_array[256];
int main()
{
char ch;
FILE *fp;
int n=0;
char *str;
printf("Enter filepath\n");
gets(file_name);
fp = fopen(file_name,"r");
if( fp == NULL )
{
perror("Error opening the file.\n");
exit(EXIT_FAILURE);
}
int i = 0;
char *p;
while( ( ch = fgetc(fp) ) != EOF )
{
char *fgets(char *str, int n, FILE *stream);
p = strtok(str, " ");
i=0;
while(p!=NULL)
{
strcpy(token_array[i], p);
}
i++;
}
for(n=0;n<256;n++)
{
printf("%s", &token_array[n]);
}
return 0;
}
You can try this code instead. I changed your program so that it can read and tokenize the file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *trim(char *s) {
int i = strlen(s) - 1;
if (s[i] == '\n')
s[i] = '\0';
return s;
}
#define BUFFER_SIZE 100
char *token_array[256];
int main( int argc, char** argv ){
const char *delimiter_characters = " ";
char *filename = malloc(BUFFER_SIZE);
int i = 0;
printf("Enter filepath\n");
fgets(filename, 100, stdin);
FILE *input_file = fopen( trim(filename), "r" );
char buffer[ BUFFER_SIZE ];
char *last_token;
if( input_file == NULL ){
fprintf( stderr, "Unable to open file %s\n", filename );
}else{
// Read each line into the buffer
while( fgets(buffer, BUFFER_SIZE, input_file) != NULL ){
// Write the line to stdout
//fputs( buffer, stdout );
// Gets each token as a string and prints it
last_token = strtok( buffer, delimiter_characters );
while( last_token != NULL ){
//printf( "%s\n", last_token );
token_array[i] = malloc(100);
strcpy(token_array[i], last_token);
i++;
last_token = strtok( NULL, delimiter_characters );
}
}
if( ferror(input_file) ){
perror( "The following error occurred" );
}
fclose( input_file );
}
int n;
for(n=0;token_array[n] != NULL && n<256;n++)
{
printf("%s", token_array[n]);
free(token_array[n]);
}
free(filename);
return 0;
}
data.txt
Hello Foo Bar
How are you?
Test
Debug/gnu
Enter filepath
data.txt
HelloFooBar
Howareyou?
Process finished with exit code 0
The contents of the array are
n[0] Hello
n[1] Foo
n[2] Bar
n[3] How
n[4] are
n[5] you?
You can see the contents of the array if you add debug info:
printf("n[%d] %s\n", n, token_array[n]);
This line does nothing:
char *fgets(char *str, int n, FILE *stream);
As written, that line is nothing but a declaration of a function, probably not what you want.
If you're going to use fgets(), use fgets() alone and don't mix it with fgetc():
char str[1024];
while ( fgets( str, sizeof( str ), fp )
{
.
.
.
fgets() returns NULL upon EOF or an error condition. And note that str is not a char *, it's a char array. An even better solution would be to use getline() because fgets() with a fixed-length buffer can only read entire lines that fit into the buffer. Longer lines will be split.
fgetc() returns int, not char. But you don't shouldn't use fgetc() when reading lines from a file with fgets(). Pick one and use that. But if you use fgetc(), you'll need to write code to put together each line as you read it character-by-character.
And what does token_array[i] point to? You declare token_array as an array of pointers:
char *token_array[256];
But you never allocate any memory for each pointer in the array to point to.
The easiest solution is to change
strcpy(token_array[i], p);
to
token_array[i] = strdup(p);
assuming your platform has strdup(), which is equivalent to a malloc() and strcpy() to the memory returned by malloc(), so you need to call free() on the string you get from strdup().
Your use of strtok() is wrong. See How does strtok() split the string into tokens in C? for examples of proper strtok() usage.
And since token_array is an array of char * pointers, this
printf("%s", &token_array[n]);
will take the address of the actual pointer itself, and not the string it's supposed to point to. It will then try to print out a "string" in the memory containing the pointer variable. That's won't work well. Since it's already a char *, all you need is this:
printf("%s", token_array[n]);