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
Related
I have these in my file:
JOS BUTTLER
JASON ROY
DAWID MALAN
JONNY BAISTROW
BEN STOKES
in different lines. And I want them to extract in my program to print them on the exact way they are in file. My imaginary output screen is:
JOS BUTTLER
JASON ROY
DAWID MALAN
JONNY BAISTROW
BEN STOKES
How would I do it using fscanf() and printf(). Moreover suggest me the way to change the delimiters of fscanf() to \n
I have tried something like this:
char n[5][30];
printf("Name of 5 cricketers read from the file:\n");
for(i=0;i<5;i++)
{
fscanf(fp,"%[^\n]s",&n[i]);
printf("%s ",n[i]);
}
fclose(fp);
}
But it works only for the first string and other string could not be displayed. There were garbage values.
Be protected from buffer overflows limiting the length of the input, use "%29[^\n]" instead of "%[^\n]s" (you don't need the s specifier)
Consume the trailing new line (your wildcard ^\n reads until a new line is found) using %*c, * means that a char will be read but won't be assigned:
fscanf(fp, "%29[^\n]%*c", n[i]);
or better yet (as pointed out by #WeatherVane), add a space before %, this will consume any blank space including tabs, spaces and new lines that may be left in the buffer from the previous read:
fscanf(fp, " %29[^\n]", n[i]);
Notice that you don't need an ampersand in &n[i], fscanf wants a pointer but n[i] is already (decays into) a pointer when passed as an argument.
Finally, as pointed out by #paddy, fgets does all that for you and is a safer function, always prefer fgets.
How to get string terminated with new line in file handling using fscanf
Use fgets() to read a line of input into a string. It also reads and saves the line's '\n'.
Buffer size 30 may be too small, consider 60.
To detect if the line is too long and lop off the '\n', read in at least + 2 characters.
// char n[5][30];
#define NAME_N 5
#define NAME_SIZE 30
char n[NAME_N][NAME_SIZE]
char buf[NAME_SIZE + 2]
while (i < NAME_N && fgets(buf, sizeof buf, fp) != NULL) {
size_t len = strlen(buf);
// Lop off potential trailing '\n'
if (len > 0 && buf[len - 1] == '\n') {
buf[--len] = '\0';
}
// Handle unusual name length
if (len >= NAME_SIZE || len == 0) {
fprintf(stderr, "Unacceptable name <%s>.\n", buf);
exit(EXIT_FAILURE);
}
// Success
strcpy(n[i], buf);
printf("%s\n", n[i]);
i++;
}
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 understand what the following code does
void chomp (char* string, char delim) {
size_t len = strlen (string);
if (len == 0) return;
char* nlpos = string + len - 1;
if (*nlpos == delim) *nlpos = '\0';
}
what is a delimiter?. Does the fourth line basically saves the last character in the string?
If the last character of the string matches delim, then that characters position in the string (*nlpos) is assigned a zero byte, which effectively terminates the C string one position closer to the beginning of the string.
I think that the term chomp became popular with Perl that often trimmed off the terminating newline when doing line by line processing.
The delimiter is the newline character.
Then string length is counted and type set to length (size_t formats lenghth into a ISO defined type that represents size).
Length of string is checked for zero (0) length and then returns to calling routine if true
This code will cut away the delimiter in a string (can be a buffer) and put null character(\0) at the end.
The fourth line will store the last char in the string and replaces it with the null character.
Delimiter is sequence of characters used to specify a boundary in plain text or region. Hence it will come at the end.
The NULL character is used in C style character strings to indicate where the end of the string is.
Okay. So I'm reading and storing text from a text file into a char array, this is working as intended. However, the textfile contains numerous newline escape sequences. The problem then is that when I print out the string array with the stored text, it ignores these newline sequences and simply prints them out as "\n".
Here is my code:
char *strings[100];
void readAndStore(FILE *file) {
int count = 0;
char buffer[250];
while(!feof(file)) {
char *readLine = fgets(buffer, sizeof(buffer), file);
if(readLine) {
strings[count] = malloc(sizeof(buffer));
strcpy(strings[count], buffer);
++count;
}
}
}
int main() {
FILE *file1 = fopen("txts", "r");
readAndStore(&*file1);
printf("%s\n", strings[0]);
printf("%s\n", strings[1]);
return 0;
}
And the output becomes something like this:
Lots of text here \n More text that should be on a new line, but isn't \n And so \n on and
and on \n
Is there any way to make it read the "\n" as actual newline escape sequences or do I just need to remove them from my text file and figure out some other way to space out my text?
No. Fact is that \n is a special escape sequence for your compiler, which turns it into a single character literal, namely "LF" (line feed, return), having ASCII code 0x0A. So, it's the compiler which gives a special meaning to that sequence.
Instead, when reading from file, \n is read as two distinct character, ASCII codes 0x5c,0x6e.
You will need to write a routine which replaces all occurences of \\n (the string composed by characters \ and n, the double escape is necessary to tell the compiler not to interpret it as an escape sequence) with \n (the single escape sequence, meaning new line).
If you only intend to replace '\n' by the actual character, use a custom replacement function like
void replacenewlines(char * str)
{
while(*str)
{
if (*str == '\\' && *(str+1) == 'n') //found \n in the string. Warning, \\n will be replaced also.
{
*str = '\n'; //this is one character to replace two characters
memmove(str, str+1, strlen(str)); //So we need to move the rest of the string leftwards
//Note memmove instead of memcpy/strcpy. Note that '\0' will be moved as well
}
++str;
}
}
This code is not tested, but the general idea must be clear. It is not the only way to replace the string, you may use your own or find some other solution.
If you intend to replace all special characters, it might be better to lookup some existing implementation or sanitize the string and pass it as the format parameter to printf. As the very minimum you will need to duplicate all '%' signs in the string.
Do not pass the string as the first argument of printf as is, that would cause all kinds of funny stuff.
I'm new to C programming. I am trying to make a program that takes some simple input. However I found that on comparison of my input string to what the user "meant" to input, there is an additional character at the end. I thought this might be a '\0' or a '\r' but that seems not to be the case. This is my snippet of code:
char* getUserInput(char* command, char $MYPATH[])
{
printf("myshell$ ");
fgets(command, 200, stdin);
printf("%u\n", (unsigned)strlen(command));
if ((command[(unsigned)strlen(command) - 1] == '\0') || (command[(unsigned)strlen(command) - 1] == '\r'))
{
printf("bye\n");
}
return command;
}
The code shows that when entering, say "exit" that 5 characters are entered. However I can't seem to figure out the identity of this last one. "Bye" never prints. Does anyone know what this mystery character could be?
The magical 5th element most probably is a newline character: \n
From man fgets() (emphasis by me):
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A '\0' is
stored after the last character in the buffer.
To prove this print out each character read by doing so:
char* getUserInput(char* command, char $MYPATH[])
{
printf("myshell$ ");
fgets(command, 200, stdin);
printf("%u\n", (unsigned)strlen(command));
{
size_t i = 0, len = strlen(command);
for (;i < len; ++i)
{
fprintf(stderr, "command[%zu]='%c' (%hhd or 0x%hhx)\n", i, command[i], command[i], command[i]);
}
}
...
assumptions
array indexes in c are started with 0
strlen returns length of string
so, if you have string "exit", this will be 5 symbols in array = e, x, i, t, \0, strlen return 4, but you're trying to decrement it by 1, so you're checking last symbol in string, instead on NULL terminator
to check NULL terminator use command[strlen(command)] - this will give you \0 always, so there is no sense in it
if you want to compare strings use strcmp function
UPDATE: issue with your program is because fgets appends \n symbol at then end of string:
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.
The reason you don't see the last char is because strlen() won't calculate '\0' into the string's length. So testing for '\0' wont succeed.
for instance, const char* a = "abc"; then strlen(a) will be 3. if you want to test it, you need to access it by command[strlen(command)]
The reason for getting strlen equals to 5 on "exit" is because fgets will append the '\n' character at the end of the input. You could test it by command[strlen(command) -1 ] == '\n'