Loop counter or break statement is not working - c

I'm trying to write a program that takes in user input from keyboard, stores it in a 2D array, and prints it in revers order. So, if a user typed in:
Line 1
Line 2
The output would be:
Line 2
Line 1
However, I'm stuck on a break condition in my if statement inside the first for loop. Even though I type in "STOP" the program still waits for input. I assume the problem might be due to strcmp function because when I print out the value returned from the function, I'm not getting zero even though my input was "STOP".
#include <stdio.h>
#include <string.h>
int main(){
int i, words = 500, characters = 100, arraylen;
char array[words][characters];
arraylen = sizeof(array)/sizeof(array[0][0]);
printf("Enter lines of words( type \"STOP\" to quit):\n");
for(i = 0; i < arraylen; i++){
fgets(array[i], 100, stdin);
//printf("Value at index %d is %s", i, array[i]);
//printf("Value of strcmp: %d\n", strcmp(array[i], "STOP"));
if(strcmp(array[i], "STOP") == 0){
//if(fgets(array[i], 500, stdin) == "STOP")
break;
}
}
printf("\n");
for(i = arraylen - 1; i >= 0; i--){
printf("%s", array[i]);
}
printf("\n");
return 0;
}

The maximum length of array is really just the value of words.
You also need to need to keep track of how many entries you've added so that you do not run out of space, and so that you can know which position to start printing from, afterwards. As is, you are attempting to print from the very end of the array, from memory that may not have been initialized.
fgets places the newline character ('\n'), if read, in the buffer. You'll either need to remove it, or use strncmp to limit your comparison to the length of your sentinel string.
if (strncmp(buffer, "STOP", 4)) {
/* .. */
}
fgets can also fail, returning NULL to signal this. You need to check its return value in some way, and act appropriately.
An example program:
#include <stdio.h>
#include <string.h>
#define MAX_LEN 500
#define STR_LEN 100
int main(void) {
char strings[MAX_LEN][STR_LEN];
size_t i = 0;
printf("Enter lines of words( type \"STOP\" to quit):\n");
while (i < MAX_LEN && fgets(strings[i], STR_LEN, stdin)) {
strings[i][strcspn(strings[i], "\n")] = '\0';
if (strcmp(strings[i], "STOP") == 0)
break;
i++;
}
while (i--)
printf("%s\n", strings[i]);
}

Related

Why is this code producing an infinite loop?

#include <Stdio.h>
#include <string.h>
int main(){
char str[51];
int k = 1;
printf("Enter string\n");
scanf("%s", &str);
for(int i = 0; i < strlen(str); i++){
while(str[k] != '\0')){
if(str[i] == str[k]){
printf("%c", str[i]);
k++;
}
}
}
return 0;
}
It is simple C code that checks for duplicate characters in string and prints the characters. I am not understanding why it is producing an infinite loop. The inner while loop should stop when str[k] reaches the null terminator but the program continues infinitely.
Points to know
You don't need to pass the address of the variable str to scanf()
Don't use "%s", use "%<WIDTH>s", to avoid buffer-overflow
Always check whether scanf() conversion was successful or not, by checking its return value
Always use size_t to iterator over any array
i < strlen(str), makes the loop's time complexity O(n3), instead of O(n2), which also isn't very good you should check whether str[i] != 0. But, many modern compilers of C will optimize it by the way.
#include <Stdio.h> it is very wrong, stdio.h != Stdio.h
Call to printf() can be optimized using puts() and putc() without any special formatting, here also modern compiler can optimize it
while(str[k] != '\0')){ has a bracket (')')
Initialize your variable str using {}, this will assign 0 to all the elements of str
Better Implementation
My implementation for this problem is that create a list of character (256 max) with 0 initialized, and then add 1 to ASCII value of the character (from str) in that list. After that print those character whose value was greater than 1.
Time Complexity = O(n), where n is the length of the string
Space Complexity = O(NO_OF_CHARACTERS), where NO_OF_CHARACTERS is 256
Final Code
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
static void print_dup(const char *str)
{
size_t *count = calloc(1 << CHAR_BIT, sizeof(size_t));
for(size_t i = 0; str[i]; i++)
{
count[(unsigned char)str[i]]++;
}
for (size_t i = 0; i < (1 << CHAR_BIT); i++)
{
if(count[i] > 1)
{
printf("`%c`, count = %zu\n", i, count[i]);
}
}
free(count);
}
int main(void) {
char str[51] = {};
puts("Enter string:");
if (scanf("%50s", str) != 1)
{
perror("bad input");
return EXIT_FAILURE;
}
print_dup(str);
return EXIT_SUCCESS;
}
Read your code in English: You only increment variable k if character at index k is equal to character at index i. For any string that has different first two characters you will encounter infinite loop: char at index i==0 is not equal to char at index k==1, so k is not incremented and while(str[k]!=0) loops forever.

How do I read the number of characters from a input in C?

I am trying to read the number of characters including, the spaces.
I use the scanf function to check for chars using %c. Also on a side note, how would I go about storing the input into an array?
#include <stdio.h>
int main(void) {
char n, count= 0;
while (scanf("%c", &n) != EOF) {
count = count+1;
}
printf("%d characters in your input \n", count);
return 0;
}
When I test input (with spaces) such as
abcdefg
it doesn't print anything.
Defining a MAX_CHAR and checking that in loop would protect you against invalid memory write.
Remember that last byte of an array should be left for '\0', if you want to print or use the char array.
#include <stdio.h>
#define MAX_CHAR 100
int main(void) {
char n[MAX_CHAR]={0}, count= 0;
while((count!=MAX_CHAR-1)&&(scanf("%c",&n[count])==1))
{
if((n[count]=='\n')){
n[count]=0;
break;
}
count++;
}
printf("%d characters in your input [%s]\n", count, n);
return 0;
}
scanf does return EOF when it reaches the end of the file. But in order for you to see that happening, you should give your program a file input when you call it like this:
./a.out < input.txt
Inside input.txt you could put any text you want. But if you want to work in the command line, you should read until you find a \n
#include <stdio.h>
int main(void) {
char n, count = 0;
scanf("%c", &n);
while (n != '\n') {
count = count+1;
scanf("%c", &n);
}
printf("%d characters in your input \n", count);
return 0;
}
If you want to store the input in an array, you must know the size of the input (or at least the maximum size possible)
#include <stdio.h>
int main(void) {
char n, count = 0;
char input[100]; //the max input size, in this case, is 100
scanf("%c", &n);
while (n != '\n') {
scanf("%c", &n);
input[count] = n; //using count as the index before incrementing
count = count+1;
}
printf("%d characters in your input \n", count);
return 0;
}
Furthermore, if don't know the size or max size of the input, you'd have to dynamically change the size of the input array. But I think that would be a little advanced for you right now.
Your printf doesn't print anything because runtime doesn't reach to it. Your code looping for ever in while loop
while (scanf("%c", &n) != EOF) {
count = count+1;
}
because scanf won't return EOF in this case

Code Blocks error when using while(scanf) in C

I have attached a piece of code below which works perfectly fine in an online compiler but fails to work in Code Blocks compiler when using C. I have attached screenshots as well.
#include <stdio.h>
int main() {
int i = 0;
int array[100];
while(scanf("%d",&array[i])>0)
{
i++;
}
for(int j=0;j<i;j++)
{
printf("%d ",array[j]);
}
return 0;
}
Using Online compiler(GeeksForGeeks)
Using CODEBLOCKS compiler
There is no error, your while loop will go on until an invalid input is entered, you have no limit for the number of inputs so it will continue taking values, which may later become a problem since your container only has space for 100 ints.
It stops on some online compilers because of the way they use stdin inputs, it's basically a one time readout.
Examples:
It stops here, has one time stdin readout.
It doesn't stop here, has a console like input/output.
So if you want to stop at a given number of inputs you can do something like:
//...
while (i < 5 && scanf(" %d", &array[i]) > 0)
{
i++;
}
//...
This will read 5 ints, exit the loop and continue to the next statement.
If you don't really know the number of inputs, you can do something like:
//...
while (i < 100 && scanf("%d", &array[i]) > 0) { // still need to limit the input to the
// size of the container, in this case 100
i++;
if (getchar() == '\n') { // if the character is a newline break te cycle
// note that there cannot be spaces after the last number
break;
}
}
//...
The previous version lacks some error checks so for a more comprehensive approach you can do somenthing like this:
#include <stdio.h>
#include <string.h> // strcspn
#include <stdlib.h> // strtol
#include <errno.h> // errno
#include <limits.h> // INT_MAX
int main() {
char buf[1200]; // to hold the max number of ints
int array[100];
char *ptr; // to iterate through the string
char *endptr; // for strtol, points to the next char after parsed value
long temp; //to hold temporarily the parsed value
int i = 0;
if (!fgets(buf, sizeof(buf), stdin)) { //check input errors
fprintf(stderr, "Input error");
}
ptr = buf; // assing pointer to the beginning of the char array
while (i < 100 && (temp = strtol(ptr, &endptr, 10)) && temp <= INT_MAX
&& errno != ERANGE && (*endptr == ' ' || *endptr == '\n')) {
array[i++] = temp; //if value passes checks add to array
ptr += strcspn(ptr, " ") + 1; // jump to next number
}
for (int j = 0; j < i; j++) { //print the array
printf("%d ", array[j]);
}
return EXIT_SUCCESS;
}

C program Need help fixing my code for a word sort program

Hi I am still new to c and have been working on this word sort program for some time now. the guidelines are:
Write a program that sorts a series of words entered by the user. Assume that each word is no more than 20 characters long. Stop reading when the user enters an empty word. Store each word in a dynamically allocated string, using an array of pointers (use the read_line function). After all lines have been read sort the array. Then use a loop to print the words in sorted order.
The problem I seem to be having is that the program will accept words but when I enter the empty word it goes to a new line and nothing happens. An help or advice would be greatly appreciated. here is my code so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 20
#define LIM 20
int read_line(char str[], int n);
void sort_str(char *list[], int n);
int alpha_first(char *list[], int min_sub, int max_sub);
int main(void)
{
char *list[LIM];
char *alpha[LIM];
char word_str[LEN];
int word, i, j, num_count = 0;
for(;;){
printf("Enter a word: ");
scanf("%s", &word);
if(word == NULL)
break;
else
read_line(word_str, LEN);
list[i] = malloc(strlen(word_str) + 1);
strcpy(list[i], word_str);
alpha[i] = list[i];
}
sort_str(alpha, i);
for(i = 0; i < num_count; ++i){
printf("Sorted: ");
puts(list[i]);
}
return (0);
}
int read_line(char str[], int n)
{
int ch, i = 0;
while ((ch = getchar()) != '\n')
if (i < n)
str[i++] = ch;
str[i] = '\0';
return i;
}
void sort_str(char *list[], int n)
{
int i, index_of_min;
char *temp;
for (i= 0; i < n - 1; ++i) {
index_of_min = alpha_first(list, i, n - 1);
if (index_of_min != i) {
temp = list[index_of_min];
list[index_of_min] = list[i];
list[i] = temp;
}
}
}
int alpha_first(char *list[], int min_sub, int max_sub){
int i, first;
first = min_sub;
for(i = min_sub + 1; i <= max_sub; ++i){
if(strcmp(list[i], list[first]) < 0){
first = i;
}
}
return (first);
}
Your logic flow is flawed. If a word is entered, the scanf() will eat it from stdin and store a null-terminated string at the address of the integer 'word'. Any more than 3/7 chars entered, (32/64 bit, allowing for the null terminator), will start corrupting the stack. read_line() will then only have the line terminator to read from stdin, (assuming the UB doesn't blow it up first).
The problem I seem to be having is that the program will accept words but when I enter the empty word it goes to a new line and nothing happens.
There are several problems with this:
char word_str[LEN];
int word, i, j, num_count = 0;
/* ... */
scanf("%s", &word);
if(word == NULL)
break;
First, scanf("%s", &word) scans whitespace-delimited strings, and to that end it skips leading whitespace, including newlines. You cannot read an "empty word" that way, though you can fail to read a word at all if the end of the input is reached (or an I/O error occurs) before any non-whitespace characters are scanned.
Second, you are passing an inappropriate pointer to scanf(). You should pass a pointer to a character array, but you instead pass a pointer to an int. It looks like maybe you wanted to scan into word_str instead of into word.
Third, your scanf() format does not protect against buffer overflow. You should provide a field width to limit how many characters can be scanned. Moreover, you need to be sure to leave room for a string terminator.
Fourth, you do not check the return value of scanf(). If it fails to match any characters to the field, then it will not store any. Since it returns the number of fields that were successfully scanned (or an error indicator), you can detect this condition.
One way to correct the scanf() and "empty word" test would be:
int result;
result = scanf("%*[ \t]%19[^ \t\n]", word_str);
if (result < 1) break;
(That assumes a fixed maximum word length of 19 to go with your declared array length of 20.) You have several additional problems in your larger code, large among them that read_line() attempts to read the same data you just read via scanf() (in fact, that function looks altogether pointless). Also, you never update num_count, and after calling sort_str() you lose track of the number of strings you've read by assigning a new value to variable i.
There may be other problems, too.

How can we restrict user to enter characters and also integers greater than specified length in C?

I'm trying to create a C program on OTP (One Time Pad) encryption. The program takes a string to be encrypted from the user. Then it has to ask for the length of the key before taking the key (in integer). Since I want the program to be 100% correct, I'm putting a constraint on the length of key. As we know, in OTP the length of the key has to be in integers can't exceed the length of the text. So, how can we implement such a filter? I've tried creating the code but it is not working.
Here's the code:
//An Under-Construction program to implement OTP (One time Pad) encryption
#include "stdio.h"
#include "cstring"
#include "ctype.h"
int main()
{
char str[10000], key[10000];
printf("Enter the string:- ");
scanf("%[^\n]", str); //stops scanning when user presses return
int len /* stores the number of digits of the OTP key*/, isalphabet=0;
do
{
printf("What is the length of the key you are entering?:-");
scanf("%d", &len);
if( isalpha(len) ) // Checks if len is a character
{
isalphabet=NULL; //isalphabet becomes NULL if it is a character and not an integer
}
} while (len > strlen(str) || isalphabet == NULL); //reiterate the loop until the conditions are satisfied
for(int i = 0; i < len; i++)
{
printf("%dth digit of Key= ", i+1);
scanf("%d", &key[i]);
}
return(0);
}
I want the program to take only integer value from the user while scanning 'len' and also the value of 'len' shouldn't exceed the length of the string to be encrypted, and reiterate the loop if these conditions aren't satisfied. Can someone point out my mistake and show the the solution? Also, please explain me the reason as to why isn't the code working as it should.
check scanf("%d", len); is there somewhere a & missing? also initialize len
Update:-
sorry for being late,
okk, actually there's few things you need to correct, sorry i didn't point them in first post.
1) correct the header inclusion delimiter. Use <stdio.h> instead of "stdio.h"
2) initialize len = 0
3) flush stdin after you have read. If you really enter a char, the scanf(%d,&len) is not going to clear it/read it. So you will be stuck in an infinite loop as because of a char stucking in stdin. same goes for the last for loop. Fortunately here you will not be stuck, but the loop will finish prematurely.
4) isalphabet=NULL, isalphabet is int, NULL basically a void pointer with 0x0 value, you should assign 0 to an int.
5) So you came inside the loop with isalphabet=0, the number is not a alphabet, you did not touch the isalphabet, and end of while loop, isalphabet==NULL, here perhaps it will run as true and again the while loop starts. So when is the loop breaking condition getting set to isalphabet?
6) Also why use the cstring in c code? why not string.h (but this is more of a personal choice :))
7) correcting the len > strlen( to len >= strlen
I edited a little bit, check if it works
//An Under-Construction program to implement OTP (One time Pad) encryption
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
char str[10000], key[10000];
printf("Enter the string:- ");
scanf("%[^\n]", str); //stops scanning when user presses return
int len /* stores the number of digits of the OTP key*/, isalphabet=0;
do
{
printf("What is the length of the key you are entering?:-");
scanf("%d", &len);
fflush(stdin);
if( isalpha(len) ) // Checks if len is a character
{
isalphabet=1; //isalphabet becomes NULL if it is a character and not an integer
}
} while (len >= strlen(str) || isalphabet == 1); //reiterate the loop until the conditions are satisfied
int i;
for(i = 0; i < len; i++)
{
printf("%dth digit of Key= ", i+1);
scanf("%d", &key[i]);
}
return(0);
}
First, scanf("%d", len); should be
scanf("%d", &len);
The strlen(str) returns the length, and the comparison should be
len > (strlen(str) -1)
and the comparisons for if is an alpha or not, could be done inside the while loop.
Check this code.
#include "stdio.h"
#include "string.h"
#include "ctype.h"
#define TRUE 1
#define FALSE 0
int main()
{
char str[10000];
char key[10000];
printf("Enter the string:- ");
scanf("%[^\n]", str); //stops scanning when user presses return
int len = 0;
int isalphabet= TRUE;
int apply = 1;
do
{
printf("What is the length of the key you are entering?:-");
scanf("%d", &len);
isalphabet= isalpha(len);
apply = (len > (strlen(str) -1)) ;
} while (!apply || isalphabet); //reiterate the loop until the conditions are satisfied
int i;
for(i = 0; i < len; i++)
{
printf("%dth digit of Key= ", i+1);
scanf("%c\n", &key[i]);
}
for(i = 0; i < len; i++){
printf("key[%d] = %c\n", i, key[i]);
}
return(0);
}

Resources