Simple Loops and String Length in C - c

I'm pretty new to C. Writing in Visual Studio 2015, I'm trying to safely prompt a user for a string by using fgets. I want to use fgets to get the string, check if the string is too long, and reprompt the user if it is until they enter a good string. Here is my code
/*
* Nick Gilbert
* COS317 Lab 2 Task 2
*/
#include "stdafx.h"
int main()
{
char str[10];
int isValid = 0;
while (isValid == 0) {
printf("Please enter a password: ");
fgets(str, 10, stdin);
if (strlen(str) == 9 && str[8] != '\n') { //http://stackoverflow.com/questions/21691843/how-to-correctly-input-a-string-in-c
printf("Error! String is too long\n\n");
memset(&str[0], 0, sizeof(str));
}
else {
printf(str);
isValid = 1;
}
}
printf("Press 'Enter' to continue...");
getchar();
}
However, when I run this and enter a bad string, the excess characters get fed into the next fgets automatically!
How can I fix this to do what I want it to do?

If the string read in by fgets doesn't end with a newline, call fgets in a loop until it does, then prompt the user again.
if (strlen(str) > 0 && str[strlen(str)-1] != '\n') {
printf("Error! String is too long\n\n");
do {
fgets(str, 10, stdin);
} while (strlen(str) > 0 && str[strlen(str)-1] != '\n') {
}
Also, never pass a variable at the first argument to printf, particularly if the contents of that variable comes from user entered data. Doing so can lead to a format string vulnerability.

Try this:
#include "stdafx.h"
int main()
{
char str[10];
int isValid = 0;
while (isValid == 0) {
printf("Please enter a password: ");
fgets(str, str, stdin);
if (strlen(str) == 9 && str[8] != '\n') { //http://stackoverflow.com/questions/21691843/how-to-correctly-input-a-string-in-c
printf("Error! String is too long\n\n");
memset(str, 0, sizeof(str));
}
else {
printf("%s",str);
isValid = 1;
}
}
printf("Press 'Enter' to continue...");
getchar();
}
In addition:
While using memset() you can directly use the array_name rather &array_name[0].

Related

How to compare two char arrays in C?

I'm coming from Python and there you can easily compare two strings (char arrays) like that:
if "foo" == "bar":
# ...
How would I do this in C? I already saw this post but it didn't work.
Code:
int main(void) {
char string[100];
printf("Please enter something: ");
fgets(string, 100, stdin);
if (strcmp(string, "a") == 0)
printf("a");
else if (strcmp(string, "b") == 0)
printf("b");
else if (strcmp(string, "c") == 0)
printf("c");
else
printf("something else");
return (0);
}
It prints "something else" though I entered a.
The function fgets can append to the entered string the new line character '\n' that you should remove. For example
fgets(string, 100, stdin);
string[ strcspn( string, "\n" ) ] = '\0';
or
fgets(string, 100, stdin);
char *p = strchr( string, '\n' );
if ( p != NULL ) *p = '\0';
From the C Standard (7.21.7.2 The fgets function)
2 The fgets function reads at most one less than the number of
characters specified by n from the stream pointed to by stream into
the array pointed to by s. No additional characters are read after a
new-line character (which is retained) or after end-of-file. A null
character is written immediately after the last character read into
the array.
The fgets() also takes in the newline character when the user presses the Enter key. So in order to remove that from what is stored in `string[100], just change :
fgets(string, 100, stdin);
to
strtok(fgets(string, 100, stdin), "\n");
to remove the newline character. Just make sure to include the #include <string.h> header
Further Reading
If you are wondering what strtok does, have a look at https://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm
The C library function char *strtok(char *str, const char *delim)
breaks string str into a series of tokens using the delimiter delim.
char *strtok(char *str, const char *delim)
You could answer this question yourself if you did put some research effort.
int main(void) {
char string[100];
printf("Please enter something: ");
fgets(string, 100, stdin);
if (strcmp(string, "a") == 0)
printf("a");
else if (strcmp(string, "b") == 0)
printf("b");
else if (strcmp(string, "c") == 0)
printf("c");
else
{
printf("something else - lets check why:\n Entered string:\n");
for(size_t n = 0; n <= strlen(string); n++)
{
printf("string[%2zu] = ", n);
switch(string[n])
{
case '\n':
printf("\\n");
break;
case '\r':
printf("\\r");
break;
case 0:
printf("null char");
break;
default:
if(string[n] < ' ' || string[n] > 127)
{
printf("\\x%x", (unsigned)string[n]);
}
else
printf("'%c'", string[n]);
}
printf("\n");
}
}
return (0);
}
https://godbolt.org/z/afb3Ej7E9

creating username function what if there is no input at all just pressing enter?

How do I make an error message if only enter or a space is entered?
do
{
printf("Please enter a username: ");
scanf("%s", name);
if(name[0] == '\n')
{
printf("invalid input");
}
printf("> %s\n", name);
}
while(strlen(name) < 2 || strlen(name) > 15);
The newline will result in an empty string so the format specifier is not satisfied, so scanf() does not return. It is somewhat arcane behaviour, but:
int count = scanf( "%16[^ \n]s", name ) ;
will return when newline or leading whitespace is entered with count == 0. It will also accept no more than 16 characters, preventing a buffer overrun while allowing the > 15 characters test.
To avoid unnecessary tests and multiple calls to strlen() for the same string:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
int main()
{
char name[20] = "" ;
bool name_valid = false ;
while( !name_valid )
{
printf("Please enter a username: ");
int count = scanf("%16[^ \n]", name);
size_t len = count == 0 ? 0 : strlen( name ) ;
name_valid = len > 1 && len < 16 ;
if( !name_valid )
{
int ch ;
do
{
ch = getchar() ;
} while( ch != '\n' && ch != EOF ) ;
printf("invalid input\n");
}
}
printf("> %s\n", name);
return 0;
}
Note that in "invalid input" you need to remove the buffered newline and any preceding junk.
I personally don't like using scanf() b/c it results in a lot of trouble and it is not safe to use it in a production environment. I recommend using fgets() instead, and here is how it works:
#include <stdio.h>
#include <string.h>
int main()
{
char buffer[50];
int buffer_size = sizeof(buffer);
/* accepts string input from user */
printf("Please enter a username: ");
fgets(buffer, buffer_size, stdin);
/* then remove "\n" from the 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.
*/
buffer[strcspn(buffer, "\n")] = 0;
/* check if user has entered an empty string */
/* strcmp(): compares two strings and returns 0 if comparision is true */
if ((strcmp(buffer, "")) == 0 || (strcmp(buffer, " ")) == 0)
printf("I can detect that you printed nothing! \n");
else
printf("You printed: %s", buffer);
return 0;
}
It may seem like an absurd amount of work to do just to get input from user, but this is how it works in C.

Using fgets() to recieve a sentence input

I seem to be having an issue with some code. The purpose of the code is to take a phrase and convert it to pig latin.
It seems that this code will not take user input, at the block where we say if (x == 1). What it will do is it will automatically take NULL as input to fgets, and I'm clueless as to why.
I've spent entirely too much time on this problem, and I would appreciate any advice on how to improve this code. Please leave a comment on how I can improve my questions in the future.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int pigLatin()
{
char phrase[250] = { 0 };
char pigPhrase[300] = { 0 };
char * tokens[300] = { 0 };
char fileName[260] = { 0 };
FILE * read = NULL;
FILE * write = NULL;
int i = 0;
int x;
int size;
while (i < 10000) {
i++;
x = 0;
printf("Enter one(1) to input via console, two(2) to input via .txt, or (3) to exit:\n");
scanf_s("%d", &x);
if (x == 1) {
printf_s("Enter your Phrase Do not include:\nany punctuation, words less than 2 letters long, or words seperated by blanks:");
fgets(phrase, sizeof phrase, stdin);
phrase[strlen(phrase) - 1] = '\0';
printf_s("\nPhrase Entered:%s\n", phrase);
system("pause");
}
else if (x == 2)
{
printf("Enter name of input file:\n");
scanf_s("%s", fileName, 260);
printf("File name:\n%s\n", fileName);
if (fopen_s(&write, fileName, "r") == 0)
{
scanf_s("%s", phrase, 260);
}
}
else if (x == 3)
{
break;
}
else
{
printf("Invalid Statement\n");
break;
}
}
return 0;
}
scanf("%d", &number); will read an integer but leave everything else in the stream including the '\n' generated by pressing [Enter] after entering the number. This newline left in the stream is then consumed by fgets() without giving you a chance for input.
Clear the stream after using scanf():
int clear(FILE *stream)
{
int ch; // reads until EOF or a newline is encountered:
while((ch = fgetc(stream)) != EOF && ch != '\n');
}
// ...
int number;
if(scanf("%d", &number) != 1) {
// handle error;
}
clear(stdin);
char foo[42];
fgets(foo, sizeof(foo), stdin);
// ...

Using scanf for char array in while loop

I am new to C programming.
I was curious as to see how much I have learnt C.
Therefore I thought of creating a program in which I could simply create a file and write in it.
The name of the file, I thought, should be less that 100 chars. But it doesn't matter if it is a string or one word or a letter.
I couldn't complete because I was stuck on fact that how to input a string for a file name(eg, Project work, New Doc1, etc)
So I wrote this;
int main()
{
int a = 0;
while(a != 5)
{
puts("Put a number: ");
scanf("%i", &a);
if(a == 1)
{
char name[30];
printf("Put a name: ->>");
for(int i = 0;i < 31 && name[i] != '\n';i++)
{
name[i] = getchar();
}
char ex[50] = ".txt";
strcat(name,ex);
printf("%s",name);
}
}
return 0;
}
The problem is while inputting the name, it doesn't stop at the next (when I press enter) and some how it is not printing the right file name either.
There's a lot of problems with you approach.
It's not good to mix scanf with another input primitives, you must flush stdin from any remaining characters.
Any string must end in '\0' in order to mark that string as complete. So you must reserve space to this character.
When you concat you must obey the limit of the string.
If you use printf, the string will be only displayed after flushing the stdout (when you put '\n' in the end of the string, flush is done)
Try this:
#include <stdio.h>
#include <string.h>
int main()
{
int a = 0;
while(a != 5)
{
int ch;
puts("Put a number: ");
scanf("%d", &a);
/* flush any remaining characters */
while ((ch=getchar()) != EOF && ch != '\n'); /* issue 1 */
if(a == 1)
{
int i = 0;
char name[30];
printf("Put a name: ->>");
fflush(stdout); /* issue 4 */
while ((ch=getchar()) != EOF && ch != '\n' && i < 25) /* issue 3 */
name[i++] = ch;
name[i] = '\0'; /* issue 2 */
/* flush any remaining characters [if input > 25 chars] */
if (ch != EOF && ch != '\n') while ((ch=getchar()) != EOF && ch != '\n');
char ex[50] = ".txt";
strcat(name,ex); /* issue 3 */
printf("%s\n",name);
}
}
return 0;
}
Also, consider use getline and atoi instead of getchar and scanf
#include<stdio.h>
main()
{
static char stop_char='y';
char input=0;
do{
printf("please input a character\n");
scanf("\n%c",&input);
}while(input!=stop_char);
}

How do i remove NULL input in C?

My teacher has asked me to "Fool proof" my code from any sort of misuse, So I have come up with an
program that can remove any empty values (by disallowing them entirely)
Here is the Un-foolproofed code
#include <stdio.h>
#include <conio.h>
int main()
{
char text[16];
printf("Type something: ");
fgets(text,16, stdin);
printf("You typed: %s",text);
getch();
}
I have made some simple adjustments to ensure there is no error, however, i cannot get the if filter to work properly, as it still allows the NULL input
#include <stdio.h>
#include <conio.h>
int main()
{
char text[16];
int loop;
do
{
printf("Type something: ");
fgets(text,16, stdin);
if( text[0] == '\0')
{
printf("Try again");
system("cls");
loop=1;
}
else
{
loop = -1;
}
}
while(loop > 0);
printf("You typed: %s",text);
getch();
}
I've tried google and i cannot get a solid answer, this probably is some very simple line of code, but sadly i have no idea what it is.
Edit: it's fixed, the if statement should be:
if (text[0] == '\n')
Using the return value from fgets() is the best first step to fool-proofing user I/O.
char text[16];
printf("Type something: ");
if (fgets(text, sizeof text, stdin) == NULL) {
if (feof(stdin)) Handle_stdin_is_closed(); // no more input
if (ferror(stdin) Handle_IOerror(): // very rare event, more common with files
}
// Test is input is is only a '\n'
if (text[0] == '\n')
printf("Try again");
// Look for long line.
size_t len = strlen(text);
if (len + 1 == sizeof text && text[len - 2] != '\n') HandleLongLine();
The next step is to look for scan errors. Let's assume code is to read a long.
errno = 0;
char *endptr;
long = strtol(text, &endptr, 10);
if (errno) Handle_NumericOverflow();
if (text == endptr) Handle_InputIsNotNumeric();
while (isspace((unsigned char) *endptr)) endptr++;
if (*endptr != '\0') Handle_ExtraTextAfterNumber();
Although this is a lot of code, robust handling of hostle user input is best spun off to a helper function where lots of tests can be had.
char * prompt = "Type something: ";
long number;
int stat = GetLong(stdin, prompt, &number); // put all tests in here.
if (stat > 0) Handle_SomeFailure();
if (stat < 0) Handle_EOF();
printf("%ld\n", number);
fgets reads a whole line including the newline into the buffer and 0-terminates it.
If it reads something and then the stream ends, the read line will not have a newline.
If the line does not fit, it won't contain a newline.
If an error occurs before it successfully reads the first character, it returns NULL.
Please read the man-page for fgets: http://man7.org/linux/man-pages/man3/fgets.3.html
According to the fgets() man page
char *fgets(char *s, int size, FILE *stream);
//fgets() returns s on success, and NULL on error or when end of file
//occurs while no characters have been read.
so, you can check the return value of fgets()
n = fgets(text,16, stdin);
if that value is NULL, then nothing have been read.
you can do this by checking the value of n in a for loop,
if( n == NULL)
{
printf("Try again");
system("cls");
loop=1;
}
else
{
loop = -1;
}

Resources