I am reading from a textfile and there is a pattern. I am currently reading the file with help of tokens. There are many lines and the pattern breaks if there are any spaces or row breaks after the pattern is finished. This is what I have tried so far:
char newLine[10];
strcpy(newLine, "\n");
int stringValue;
....
*readfromfile*
{
...
stringValue = strcmp(token, newLine);
if(stringValue == 0)
{
...
So if there is a new line or blank space after the line I want the if statement to go through. Does anyone know how to solve this? Is it that token doesn't aquire the character, " " and "\n". If so, what can I do to solve it?
Just trim(newline) before calling strcmp(). trim() will remove any blanks at the beginning or the end of the string.
You can found an example in C in this question.
There's another way: if there's blanks at the end of newLine that you don't want to compare by using strcmp(), use strncmp() instead (with the length of token).
As per your comment you are reading buffer first and then want to remove characters then do as below example, (with assumption your buffer size is of 1024)
int RemoveTokens(char *string)
{
char buf[1024] = {0};
int i = 0;
int j = 0;
strncpy(buf, string, 1024);
memset(string, 0x00, 1024);
for (i=0; i<1024; i++)
{
if (' ' != buf[i] && '\n' != buf[i])
{
string[j] = buf[i];
j++;
}
}
}
Hope it will helps you to do it easily. :D
Related
Hello I am doing a looping on my code with fgets and I want that when user introduces the word "bye" the program ends, so I have a do while like this:
char buf[1000]
do{
fgets(buf, 1000, stdin);
//More code here
while(strcmp(buf, "bye")!=0);
But I have a problem that it is, when user made a space or a tab or multiple spaces before write bye the strcmp doesnt recognize him as bye, so the program only exits when users only type bye without any previous space or tab.
I want to know how can I prevent the spaces or tabs before the by word to exits if user type for example:
' bye'
fgets reads in a complete line, including any starting white spaces and also including the new line character at the end of the line. Even if a user does not enter preceding white spaces, the content of buf is likely to be "bye\n", such that buf will hardly compare equal to "bye" when using strcmp.
I'd suggest to scan the buffer for a single word using sscanf and compare this word to "bye" then. Note that scanf("%s"...) skips white space characters at the beginning of a word and stops before the first white space after the word.
char isStopWord[20];
isStopWord[0] = '\0';
sscanf(buf,"%19s",isStopWord);
}
while(strcmp(isStopWord, "bye")!=0);
It a very strange requirement to use strcmp to remove characters from the array but everything is possible :)
char *removeSpacesAndTabsBeginning(char *str)
{
size_t len;
char savedc;
if(str && *str)
{
len = strlen(str);
savedc = str[1];
str[1] = 0;
while(!strcmp(str, " "))
{
str[1] = savedc;
memmove(str, str + 1, len);
savedc = str[1];
str[1] = 0;
}
str[1] = savedc;
}
return str;
}
int main(void)
{
char z[] = " \t\tHello World.";
printf("`%s`\n", removeSpacesAndTabsBeginning(z));
}
If you want to know if the string contains "bye" use strstr.
int isBye(const char *str)
{
return !!strstr(str, "bye");
}
There are 2 problems in your code:
you should test the return value of fgets() to detect unexpected end of file.
you should ignore whitespace in the comparison. You should just trim the string read by fgets() as the other code probably does not handle these either.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main() {
char buf[1000];
while (fgets(buf, sizeof buf, stdin)) {
size_t i = 0, length = strlen(buf);
/* trim trailing white space */
while (length > 0 && isspace((unsigned char)buf[length - 1])) {
buf[--length] = '\0';
}
/* trim leading white space */
while (isspace((unsigned char)buf[i]) {
i++;
}
if (i > 0) {
memmove(buf, buf + i, length - i + 1);
}
// check for end command
if (!strcmp(buf, "bye"))
break;
//More code here: handle other commands
//...
}
return 0;
}
Is there any efficient (- in terms of performance) way for printing some arbitrary string, but only until the first new line character in it (excluding the new line character) ?
Example:
char *string = "Hello\nWorld\n";
printf(foo(string + 6));
Output:
World
If you are concerned about performance this might help (untested code):
void MyPrint(const char *str)
{
int len = strlen(str) + 1;
char *temp = alloca(len);
int i;
for (i = 0; i < len; i++)
{
char ch = str[i];
if (ch == '\n')
break;
temp[i] = ch;
}
temp[i] = 0;
puts(temp);
}
strlen is fast, alloca is fast, copying the string up to the first \n is fast, puts is faster than printf but is is most likely far slower than all three operations mentioned before together.
size_t writetodelim(char const *in, int delim)
{
char *end = strchr(in, delim);
if (!end)
return 0;
return fwrite(in, 1, end - in, stdout);
}
This can be generalized somewhat (pass the FILE* to the function), but it's already flexible enough to terminate the output on any chosen delimiter, including '\n'.
Warning: Do not use printf without format specifier to print a variable string (or from a variable pointer). Use puts instead or "%s", string.
C strings are terminated by '\0' (NUL), not by newline. So, the functions print until the NUL terminator.
You can, however, use your own loop with putchar. If that is any performance penalty is to be tested. Normally printf does much the same in the library and might be even slower, as it has to care for more additional constraints, so your own loop might very well be even faster.
for ( char *sp = string + 6 ; *sp != '\0'; sp++ ) {
if ( *sp == '\n' ) break; // newline will not be printed
putchar(*sp);
}
(Move the if-line to the end of the loop if you want newline to be printed.)
An alternative would be to limit the length of the string to print, but that would require finding the next newline before calling printf.
I don't know if it is fast enough, but there is a way to build a string containing the source string up to a new line character only involving one standard function.
char *string = "Hello\nWorld\nI love C"; // Example of your string
static char newstr [256]; // String large enough to contain the result string, fulled with \0s or NULL-terimated
sscanf(string + 6, "%s", newstr); // sscanf will ignore whitespaces
sprintf(newstr); // printing the string
I guess there is no more efficient way than simply looping over your string until you find the first \n in it. As Olaf mentioned it, a string in C ends with a terminating \0 so if you want to use printf to print the string you need to make sure it contains the terminating \0 or yu could use putchar to print the string character by character.
If you want to provide a function creating a string up to the first found new line you could do something like that:
#include <stdio.h>
#include <string.h>
#define MAX 256
void foo(const char* string, char *ret)
{
int len = (strlen(string) < MAX) ? (int) strlen(string) : MAX;
int i = 0;
for (i = 0; i < len - 1; i++)
{
if (string[i] == '\n') break;
ret[i] = string[i];
}
ret[i + 1] = '\0';
}
int main()
{
const char* string = "Hello\nWorld\n";
char ret[MAX];
foo(string, ret);
printf("%s\n", ret);
foo(string+6, ret);
printf("%s\n", ret);
}
This will print
Hello
World
Another fast way (if the new line character is truly unwanted)
Simply:
*strchr(string, '\n') = '\0';
I have a C program that reads from a txt file. The text file contains a list of words, one word per line. What I want to do is get the words from the text file and print them as one sentence/paragraph, however, when I try to print them, they still print one word per line.
I am storing the words in a 2d char array as I read them from the file. What I think is happening is the array copies the newline char from the txt file, is that correct? and if so, how do I add the word into the array without the new line char?
while(fgets(line,20,lineRead)!=NULL)
{
for(j = 0; j < 20;j++)
{
message[k][j]= line[j];
}
printf("%s", message[k]);
}
I tried a few while loops with no success:
while(line[j] != ' ')
while(line[j] != NULL)
while(line[j] != EOF)
while(line[j] != ' \')
I'm learning C so please be specific in my error. I want to understand what I'm doing wrong, not just get an answer.
Thank you!
You could simply change your for loop to be:
for(j = 0; j < 20 && line[j] != '\n';j++)
{
message[k][j]= line[j];
}
if(j < 20)
message[k][j] = '\0';
The fgets functions includes the newline character \n in the buffer you are reading. Just include a conditional statement within your loop to copy all the characters except \n and \r. Something like:
if ( line[j] != '\n' && line[j] != '\r' ) {
/* Copy the character in your new buffer */
}
The newline characters are part of the string, you need to remove them:
#include <string.h>
while(fgets(line,20,lineRead)!=NULL)
{
char* newline_pos = strpbrk (line, "\n\r"); // get first occurance of newline or carriage return
if (newline_pos)
*newline_pos = '\0';
printf("%s ", line);
}
You should do:
while(fgets(line,20,lineRead)!=NULL)
{
strcpy(message[k], line);
if(message[k][strlen(line)-1] == '\n')
message[k][strlen(line)-1] = '\0']
printf("%s", message[k]);
}
What this does is that it copies line into message[k] and then removes the last character if it is a newline character. We are checking the last character because the documentation says "A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str." So if newline is present it will be the last character.
I have a program in which I wanted to remove the spaces from a string. I wanted to find an elegant way to do so, so I found the following (I've changed it a little so it could be better readable) code in a forum:
char* line_remove_spaces (char* line)
{
char *non_spaced = line;
int i;
int j = 0;
for (i = 0; i <= strlen(line); i++)
{
if ( line[i] != ' ' )
{
non_spaced[j] = line[i];
j++;
}
}
return non_spaced;
}
As you can see, the function takes a string and, using the same allocated memory space, selects only the non-spaced characters. It works!
Anyway, according to Wikipedia, a string in C is a "Null-terminated string". I always thought this way and everything was good. But the problem is: we put no "null-character" in the end of the non_spaced string. And somehow the compiler knows that it ends at the last character changed by the "non_spaced" string. How does it know?
This does not happen by magic. You have in your code:
for (i = 0; i <= strlen(line); i++)
^^
The loop index i runs till strlen(line) and at this index there is a nul character in the character array and this gets copied as well. As a result your end result has nul character at the desired index.
If you had
for (i = 0; i < strlen(line); i++)
^^
then you had to put the nul character manually as:
for (i = 0; i < strlen(line); i++)
{
if ( line[i] != ' ' )
{
non_spaced[j] = line[i];
j++;
}
}
// put nul character
line[j] = 0;
Others have answered your question already, but here is a faster, and perhaps clearer version of the same code:
void line_remove_spaces (char* line)
{
char* non_spaced = line;
while(*line != '\0')
{
if(*line != ' ')
{
*non_spaced = *line;
non_spaced++;
}
line++;
}
*non_spaced = '\0';
}
The loop uses <= strlen so you will copy the null terminator as well (which is at i == strlen(line)).
You could try it. Debug it while it is processing a string containing only one space: " ". Watch carefully what happens to the index i.
How do you know that it "knows"? The most likely scenario is that you're simply having luck with your undefined behavior, and that there is a '\0'-character after the valid bytes of line end.
It's also highly likely that you're not seeing spaces at the end, which might be printed before hitting the stray "lucky '\0'".
A few other points:
There's no need to write this using indexing.
It's not very efficient to call strlen() on each loop iteration.
You might want to use isspace() to remove more whitespace characters.
Here's how I would write it, using isspace() and pointers:
char * remove_spaces(char *str)
{
char *ret = str, *put = str;
for(; *str != '\0'; str++)
{
if(!isspace((unsigned char) *str)
*put++ = *str;
}
*put = '\0';
return ret;
}
Note that this does terminate the space-less version of the string, so the returned pointer is guaranteed to point at a valid string.
The string parameter of your function is null-terminated, right?
And in the loop, the null character of the original string get also copied into the non spaced returned string. So the non spaced string is actually also null-terminated!
For your compiler, the null character is just another binary data that doesn't get any special treatment, but it's used by string APIs as a handy character to easily detect end of strings.
If you use the <= strlen(line), the length of the strlen(line) include the '\0' so your program can work. You can use debug and run analysis.
I am trying to make a program which needs scans in more than one word, and I do not know how to do this with an unspecified length.
My first port of call was scanf, however this only scans in one word (I know you can do scanf("%d %s",temp,temporary);, but I do not know how many words it needs), so I looked around and found fgets. One issue with this is I cannot find how to make it move to the next code, eg
scanf("%99s",temp);
printf("\n%s",temp);
if (strcmp(temp,"edit") == 0) {
editloader();
}
would run editloader(), while:
fgets(temp,99,stdin);
while(fgets(temporary,sizeof(temporary),stdin))
{
sprintf(temp,"%s\n%s",temp,temporary);
}
if (strcmp(temp,"Hi There")==0) {
editloader();
}
will not move onto the strcmp() code, and will stick on the original loop. What should I do instead?
I would scan in each loop a word with scanf() and then copy it with strcpy() in the "main" string.
maybe you can use getline method ....I have used it in vc++ but if it exists in standard c library too then you are good to go
check here http://www.daniweb.com/software-development/c/threads/253585
http://www.cplusplus.com/reference/iostream/istream/getline/
Hope you find what you are looking for
I use this to read from stdin and get the same format that you would get by passing as arguments... so that you can have spaces in words and quoted words within a string. If you want to read from a specific file, just fopen it and change the fgets line.
#include <stdio.h>
void getargcargvfromstdin(){
char s[255], **av = (char **)malloc(255 * sizeof(char *));
unsigned char i, pos, ac;
for(i = 0; i < 255; i++)
av[i] = (char *)malloc(255 * sizeof(char));
enum quotes_t{QUOTED=0,UNQUOTED}quotes=UNQUOTED;
while (fgets(s,255,stdin)){
i=0;pos=0;ac=0;
while (i<strlen(s)) {
/* '!'=33, 'ÿ'=-1, '¡'=-95 outside of these are non-printables */
if ( quotes && ((s[i] < 33) && (s[i] > -1) || (s[i] < -95))){
av[ac][pos] = '\0';
if (av[ac][0] != '\0') ac++;
pos = 0;
}else{
if (s[i]=='"'){ /* support quoted strings */
if (pos==0){
quotes=QUOTED;
}else{ /* support \" within strings */
if (s[i-1]=='\\'){
av[ac][pos-1] = '"';
}else{ /* end of quoted string */
quotes=UNQUOTED;
}
}
}else{ /* printable ascii characters */
av[ac][pos] = s[i];
pos++;
}
}
i++;
}
//your code here ac is the number of words and av is the array of words
}
}
If it exceeds the buffer size you simply can't do it.
You will have to do multiple loops
the maximum size you can scan with scanf() will come from
char *name;
scanf("%s",name);
reed this
http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html