I am trying to use getc(character) to take an element from a file and do stuff with it, but it appears that it must have a '\n' before the end of a line is met.
How can I remove this so that when I copy the characters I don't have a new line character appearing anywhere - thus allowing me to deal with printing new lines when I choose?
.
.
.
#include <string.h>
.
. /* insert stuff here */
.
char* mystring = "THIS IS MY STRING\n"
char* deststring;
.
.
.
strncpy(deststring, mystring, strlen(mystring)-1);
.
.
.
(As an added note, I'm not a huge fan of dropping \0 characters in strings like that. It doesn't work well when you start doing i18n and the character width is not fixed. UTF-8, for example, can use anywhere from 1 to 4 bytes per "character".)
To replace all new line char with spaces, use:
char *pch = strstr(myStr, "\n");
while(pch != NULL)
{
strncpy(pch, " ", 1);
pch = strstr(myStr, "\n");
}
To remove first occurrence of new line char in string, use:
char *pch = strstr(myStr, "\n");
if(pch != NULL)
strncpy(pch, "\0", 1);
Hmm, wouldn't help to use getc to fill a buffer and remove newline and carriage return characters?
You could replace it with a null terminator.
Here is one (simple) way to do it off the top of my head:
mystr[ strlen(mystr) - 1 ] = '\0';
Supposing that buf is of type char and it holds the string value read in from the file...
buf[strlen(buf)-1] = '\0';
That sets the second-last character of the buffer to nul i.e. '\0' in order to remove the new-line character.
Edit: Since loz mentioned a compiler error I suspect it's a const char * is used...Can we see the code please...
The following will do the trick
line[strlen(line) - 1] = 0
A bit more complete version:
char* end = line + strlen(line) - 1 ; // end of line
while( (end > line) && isspace(*end) ) end--; // right trim space
*(end+1) = '\0'; // terminate string
(Note: Putting a null char into it makes string readers stop reading at that point but the memory footprint of line is the same. The characters to the right of the '\0' are still there.
Related
I use an fgets to read from stdin a line and save it in a char array, I would like to get the last letter of the line i wrote , which should be in the array before \nand \0.
For example if i have a char line[10] and write on the terminal 1stLine, is there a fast way to get the letter e rather than just cycling to it?
I saw this post How do I print the last element of an array in c but I think it doesn't work for me, even if I just create the array without filling it with fgets , sizeof line is already 10 because the array already has something in it
I know it's not java and I can't just .giveMeLastItem(), but I wonder if there is a smarter way than to cycle until the char before the \n to get the last letter I wrote
code is something like
char command[6];
fgets(command,6,stdin);
If you know the sentinel value, ex: \0 (or \n ,or any value for that matter), and you want the value of the element immediately preceding to that, you can
use strchr() to find out the position of the sentinel and
get the address of retPtr-1 and dereference to get the value you want.
There are many different ways to inspect the line read by fgets():
first you should check the return value of fgets(): a return value of NULL means either the end of file was reached or some sort of error occurred and the contents of the target array is undefined. It is also advisable to use a longer array.
char command[80];
if (fgets(command, sizeof command, stdin) == NULL) {
// end of file or read error
return -1;
}
you can count the number of characters with len = strlen(command) and if this length os not zero(*), command[len - 1] is the last character read from the file, which should be a '\n' if the line has less than 5 bytes. Stripping the newline requires a test:
size_t len = strlen(command);
if (len > 0 && command[len - 1] == '\n')
command[--len] = '\0';
you can use strchr() to locate the newline, if present with char *p strchr(command, '\n'); If a newline is present, you can strip it this way:
char *p = strchar(command, '\n');
if (p != NULL)
*p = '\0';
you can also count the number of characters no in the set "\n" with pos = strcspn(command, "\n"). pos will point to the newline or to the null terminator. Hence you can strip the trailing newline with:
command[strcspn(command, "\n")] = '\0'; // strip the newline if any
you can also write a simple loop:
char *p = command;
while (*p && *p != '\n')
p++;
*p = '\n'; // strip the newline if any
(*) strlen(command) can return 0 if the file contains an embedded null character at the beginning of a line. The null byte is treated like an ordinary character by fgets(), which continues reading bytes into the array until either size - 1 bytes have been read or a newline has been read.
Once you have only the array, there is no other way to do this. You could use strlen(line) and then get the last characters position based on this index, but this basically does exactly the same (loop over the array).
char lastChar = line[strlen(line)-1];
This has time-complexity of O(n), where n is the input length.
You can change the input method to a char by char input and count the length or store the last input. Every O(1) method like this uses O(n) time before (like n times O(1) for every character you read). But unless you have to really speed optimize (and you don't, when you work with user input) should just loop over the array by using a function like strlen(line) (and store the result, when you use it multiple times).
EDIT:
The strchr() function Sourav Ghosh mentioned, does exactly the same, but you can/must specify the termination character.
A straightforward approach can look the following way
char last_letter = command[ strcspn( command, "\n" ) - 1 ];
provided that the string is not empty or contains just the new line character '\n'.
Here is a demonstrative progarm.
#include <stdio.h>
#include <string.h>
int main(void)
{
enum { N = 10 };
char command[N];
while ( fgets( command, N, stdin ) && command[0] != '\n' )
{
char last_letter = command[ strcspn( command, "\n" ) - 1 ];
printf( "%c ", last_letter );
}
putchar( '\n' );
return 0;
}
If to enter the following sequence of strings
Is
there
a
quick
way
to
get
the
last
element
that
was
put
in
an
array?
then the output will be
s e a k y o t e t t t s t n n ?
The fastest way is to keep an array of references like this:
long ref[]
and ref[x] to contain the file offset of the last character of the xth line. Having this reference saved at the beginning of the file you will do something like:
fseek(n*sizeof(long))
long ref = read_long()
fseek(ref)
read_char()
I think this is the fastest way to read the last character at the end of the nth line.
I did a quick test of the three mentioned methods of reading a line from a stream and measuring its length. I read /usr/share/dict/words 100 times and measured with clock()/1000:
fgets + strlen = 420
getc = 510
fscanf with " 100[^\n]%n" = 940
This makes sense as fgets and strlen just do 2 calls, getc does a call per character, and fscanf may do one call but has a lot of machinery to set up for processing complex formats, so a lot more overhead. Note the added space in the fscanf format to skip the newline left from the previous line.
Beside the other good examples.
Another way is using fscanf()/scanf() and the %n format specifier to write to an argument the amount of read characters so far after you have input the string.
Then you subtract this number by one and use it as an index to command:
char command[6];
int n = 0;
if (fscanf(stdin, "%5[^\n]" "%n", command, &n) != 1)
{
fputs("Error at input!", stderr);
// error routine.
}
getchar();
if (n != 0)
{
char last_letter = command[n-1];
}
#include <stdio.h>
int main (void)
{
char command[6];
int n = 0;
if (fscanf(stdin, "%5[^\n]" "%n", command, &n) != 1)
{
fputs("Error at input!", stderr);
// error routine.
}
getchar();
if (n != 0)
{
char last_letter = command[n-1];
putchar(last_letter);
}
return 0;
}
Execution:
./a.out
hello
o
I am trying to finding a string in a file. I wrote following by modifying code snippet present in man page of getline.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
FILE * fp;
char * line = NULL;
char *fixed_str = "testline4";
size_t len = 0;
ssize_t read;
fp = fopen("test.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu:\n", read);
printf("%s", line);
if (strcmp(fixed_str,line)==0)
printf("the match is found\n");
}
//printf("the len of string is %zu\n", strlen(fixed_str));
fclose(fp);
if (line)
free(line);
exit(EXIT_SUCCESS);
}
The problem is that result of strcmp is always false despite getline is successfully and correctly iterating over all lines in the file.
The length of fixed_str is 9 and that of equal string in file is 10 due to newline character (AM I RIGHT?). But comparing 9 chars with the help of strncmp still produces wrong result. I also ruled out the possibilities of caps and spaces so I think I am doing something very wrong
The test.txt is as below
test line1
test line2
test line3
testline4
string1
string2
string3
first name
I tried all entries but no success
NOTE: In my actual program I have to read fixed_str from another file
From the getline() man page (my emphasis):
getline() reads an entire line from stream, storing the address of
the buffer containing the text into *lineptr. The buffer is null-
terminated and includes the newline character, if one was found.
Your fixed_str has no newline.
Strip any newline character thus (for example):
char* nl = strrchr( line, '\n' ) ;
if(nl != NULL) *nl = `\0` ;
Or more efficiently since getline() returns the line length (in read in your case):
if(line[read - 1] == '\n' ) line[read - 1] = `\0` ;
Adding a '\n' to fixed_str may seem simpler, but is not a good idea because the last (or only) line in a file won't have one but may otherwise be a match.
Using strncmp() as described in your question should have worked, but without seeing the attempt it is hard to comment, but it is in any case a flawed solution since it would match all of the following for example:
testline4
testline4 and some more
testline4 12345.
Where fixed_str is taken from console or file input rather than a constant, the input method and data source may cause problems, as may the possibility of alternate line-end conventions. To make it more robust you might do:
// Strip any LF or CR+LF line end from fixed_str
char* line_end = strpbrk( fixed_str, "\r\n" ) ;
if( line_end != NULL ) *line_end = '\0' ;
// Strip any LF or CR+LF line end from line
line_end = strpbrk( line, "\r\n" ) ;
if( line_end != NULL ) *line_end = '\0' ;
Or the simpler (i.e. better) solution pointed out by #AndrewHenle:
// Strip any LF or CR+LF line end from fixed_str
fixed_str[strcspn(line, "\r\n")] = '\0';
// Strip any LF or CR+LF line end from line
line[strcspn(line, "\r\n")] = '\0';
That way either input can be compared regardless of lines ending in nothing, CR or CR+LF and the line end may even differ between the two inputs.
Is there a way where I can initialize an empty string array and then later ask for an input from user which is saved into the string array leaving the empty leading spaces if the input is smaller.
I am planning on using a longer string array with addition spaces so that I can do inplace character replacements .
for example :
char foo[25];
scanf(%s,foo);
foo = this is a test"
print foo;
Result be like :
"this is a test "
Your question is inconsistent, you ask about leading whitespace but your example shows trailing whitespace. If you mean trailing whitespace, you could do it this way:
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 25
int main() {
char string[BUFFER_SIZE];
memset(string, ' ', BUFFER_SIZE - 1); // initialize with spaces
string[BUFFER_SIZE - 1] = '\0'; // terminate properly
if (fgets(string, BUFFER_SIZE, stdin) != NULL) {
size_t length = strlen(string);
string[length - 1] = ' '; // replace the newline \n
if (length < BUFFER_SIZE - 1) {
string[length] = ' '; // replace extra '\0' as needed
}
printf("'%s'\n", string); // extra single quotes to visualize length
}
return 0;
}
USAGE
> ./a.out
this is a test
'this is a test '
>
The single quote were only added so you could actually see the spaces were preserved. The approach of #BLUEPIXY makes perfect sense except that it appends new whitespace to the input where you specifically asked about preserving existing whitespace.
If instead you want to preserve leading whitespace, that can probably be done as well.
So I have a homework assignment to do for Friday and I am having some trouble figuring out why this is happening. Here is the code:
while(curVal < length)
{
code[word][wordVal] = input[curVal];
if(input[curVal + 1] == 32) //Is the current char in the input a space
{
word++;
curVal++;
wordVal = -1;
}
curVal++;
wordVal++;
}
After this I print it out in a ncurses window. For the input "Lucas is great" the output is:
Lucas^D
is
great
The problem I am having is instead of printing "Lucas" it prints "Lucas^D". If anyone understand what my code is doing and can hep me fix it I would really appreciate it.
A string in C consists of an array of characters with a NUL character at the end. The NUL character can be written as '\0'. If you forget to put the NUL character at the end of your string, then all sorts of bad things can happen, including printing garbage characters and/or crashing your program.
So you have two choices. You can fill the whole array with NUL characters before you start
memset( code, '\0', sizeof(code) );
Or you can insert the NUL character when you find the end of the string.
if(input[curVal + 1] == ' ') //Is the current char in the input a space
{
code[word][wordval] = '\0';
word++;
Code does not terminate the char array properly with a '\0' to make the array a string. Thus causes subsequent printing to be amiss - likely undefined behavior.
The terminating null character '\0' should be added after each code[word][wordVal] assignment.
code[word][wordVal] = input[curVal];
// add
code[word][wordVal + 1] = '\0';
To add it inside the if(input[curVal + 1] == 32) block risks it not being set should curVal < length become false before a space is encountered.
When you copy words from input to code, you need to zero-terminate them (C strings are terminated by an extra zero byte):
code[word][wordVal] = input[curVal];
if (32 == input[curVal]) {
// The character we just read was a space.
// Transform it into a terminator.
code[word][wordVal] = 0x0;
wordVal = 0; // Prepare to write at first character...
word++; // ...of next word.
} else {
wordVal++; // Next character
}
curVal++; // Next input byte
Then you also have to terminate the last word when you reach the end of the input.
I want to get a string as input by using scanf and if the string is just a space or blank I have to print error message.
This is what I've tried to do:
char string1[20]
scanf("%s",string1)
if(string1=='')
print error message
But that didn't work, actually I didn't expect it to work because string1 is an array of chars.
Any hint how to do it?
You should note that the scanf function will never scan a string with only blanks in it. Instead check the return value of the function, if it's (in your case) less than one it failed to read a string.
You may want to use fgets to read a line, remove the trailing newline, and then check if each character in the string is a space (with the isspace function).
Like this:
char string1[20];
if (fgets(string1, sizeof(string1), stdin) != NULL)
{
/* Remove the trailing newline left by the `fgets` function */
/* This is done by changing the last character (which is the newline)
* to the string terminator character
*/
string1[strlen(string1) - 1] = '\0';
/* Now "remove" leading whitespace */
for (char *ptr = string1; *ptr != '\0' && isspace(*ptr); ++ptr)
;
/* After the above loop, `*ptr` will either be the string terminator,
* in which case the string was all blanks, or else `ptr` will be
* pointing to the actual text
*/
if (*ptr == '\0')
{
/* Error, string was empty */
}
else
{
/* Success, `ptr` points to the input */
/* Note: The string may contain trailing whitespace */
}
}
scanf() does not always skip leading blanks.
Select formats specifies like "%s", "%d", "%f" do skip leading blanks. (whitespace).
Other formats specifies like "%c", "%[]", "%n" do not skip skip leading whitespace.
Scan in line and look for spaces. (string1 may contain whitespace)
char string1[20];
// Scan in up to 19 non-LineFeed chars, then the next char (assumed \n)
int result = scanf("%19[^\n]%*c", string1);
if (result < 0) handle_IOError_or_EOF();
else if (result == 0) handle_nothing_entered();
else {
const char *p = string1;
while (isspace(*p)) p++;
if (*p == '\0')
print error message
}
First, scanf will skip any blank spaces if you put a space (or other white space characters like '\n' or '\t') before the format specifier, like scanf(" %s", &str)
Second, if(string1=='') will compare the char pointer string1 with the blank char '' which will never be true because an existing variable's address will be non-NULL. That said, there's no "blank" char like that '' in C. You need to get the line input and parse whether it is a blank line or contains only spaces