fgets -difference between array size and int num - c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char s[2];
printf("Enter some things here: ");
fgets(s, 10, stdin);
// strrev(s);
printf("\nText: %s", s);
printf("\nsize: %d\n", sizeof(s));
for(int i = 0; i < 10; i++)
printf("%c\n", s[i]);
return 0;
}
//CONSOLE:
/*Enter some things here: abcdefghiklmn
Text: abcdefghi
size: 2
a
b
(this is a symbol)
g
h
i
*/
A problem using fgets when i make the "INT" that fgets read higher than size of the arra (pic)
So where do other letters go?, what truly happens in the memmory ??
thanks everyone!
**update:
Tks everyone. Btw, i noticed that regardless of any "string" and size of s (smaller than the "int" - basically just some testing), the output will be
1. those that stored in array s
2. weird symbol ( maybe it's the "\0" to construc a string )
3. blank blank blank...
4. last part of my inputed String before.
Is there any concidences here ? Just some curiosity, tks all again ^^

Your string has a size of 2. so it can only collect from the user 1 character because after it, it has to put a '\0' for marking the end of the string.
if you want to put 10 char - try s[11].
like this you can collect 10 chars and then the last char (s[10]) will be '\0' (will be inputed there automatically).

Related

Please how can i convert arrays of charcters back to a string to display the words.(caesar cypher) In C language

I am two weeks old in learning the C language, and I have been trying to solve this problem for about 5 days now.
I have a program that is supposed to take this input: hello, world and print out the kind of encrypted word uryyb, jbeyq. My program is working good printing the words but printing them character by character on top of each other.
I want to know please if there a way I can convert those single characters back to a string so that when I run the program, it will print out the words as strings instead of character by character.
if (isupper(user_input[i]))
{
//calculating the values for the capital letters!
alphabet_index = user_input[i] - 'A'; // 65 is the ascii number of big A!
calculate_value = (alphabet_index + key) % 26;
encipher = calculate_value + 'A';
printf("cyphertext: %c\n", encipher);
that is part of my code,, When I print that cyphertext using the encipher variable, it prints out the characters on top of each other but I want to print them like normal words. I have tried all I can to no avail.
Any help will be appreciated. Thanks.
Thanks to everyone that contributed to my question, your answers made me realize my mistake which I have fixed, I just needed to print everything I needed in different places. problem solved. Thanks, guys.
Just remove the '\n' from print statement.
printf("cyphertext: %c\n", encipher); will print each character on a separate line. To have them form a single string on display, remove the unnecessary parts from the print and change it to:
printf("%c", encipher);
Here is small example of how you can do it:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char inp_str[]= "HelloWorld";
int str_len = strlen(inp_str) + 1; // get lenght of input string
char *out_str = (char *)malloc(str_len); // allocate memmory for output buffer
memset(out_str, str_len, 0); // clear output buffer with zeros
for (int i = 0; i < str_len; i++)
{
char cur_val = inp_str[i] + 6; // Caesar cipher with shift of 6
if (cur_val > 'z')
cur_val -= 32;
out_str[i] = cur_val; // encrypt and store result in out_string
}
printf("Before: %s\nAfter: %s\n", inp_str, out_str);
free(out_str); // dont forget to free memmory that you allocated
return 0;
}

Trying to return the char in the middle of an input (char array) gives "segmentation fault (core dumped)"? [duplicate]

This question already has answers here:
Why does C's printf format string have both %c and %s?
(11 answers)
Closed 4 years ago.
In a nutshell, I have to be able to return the character in the middle of an input (char array) for part of our first C assignment. What I have so far, however, is code that returns "Segmentation fault (core dumped)". I read into this a little bit, and learned that essentially I may be trying to access/modify data that is "not available to me", so-to-speak. Here is my code:
#include <stdio.h>
#include <string.h>
char input[30];
int inputLen;
char midChar;
int main()
{
printf("Type in some text, and the press the Return/Enter key: ");
fgets(input,sizeof(input),stdin);
printf("\nYour input: %s",input);
inputLen = strlen(input)-1;
printf("Length of your input is %d characters.",inputLen);
if((inputLen % 2) == 0) {
midChar = input[(inputLen/2)+1]; // >>> PROBLEM HERE <<<
}
else {
midChar = input[((inputLen+1)/2)+1]; // >>> PROBLEM HERE <<<
}
printf("%s",midChar);
return 0;
}
The two lines with >>> PROBLEM HERE <<< are the lines which I believe I've narrowed down to be the source of the problem.
Please Note: I have taken an introductory class in Java, and last semester took a class half-devoted to MATLAB, so I do have a little bit of programming intuition -- However, I am a 100% beginner in C, so I would appreciate some clear elaboration behind any help you guys may offer. I am not familiar with most functions/syntax unique to C, so I'm sure there will be cringe-worthy lines of code above for those well-versed in this language. If this is the case, feel free to include any other tips in your answers. Thanks!
You're printing a char with %s, so the program is treating your input as a pointer (to a char array). It's not a valid such thing.
You meant %c for a single character.
Your compiler should tell you about this. Turn warnings on!
A late addition:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
// This will be the default value if a string of length 0 is entered
char midChar = 0;
int inputLen;
int bufferLen = 31;
char* input = (char*)malloc(sizeof(char) * bufferLen);
printf("Type in some text, and the press the Return/Enter key: ");
fgets(input, bufferLen, stdin);
printf("\nYour input: %s", input);
inputLen = strlen(input);
if (input[inputLen - 1] == '\n') {
inputLen--; // ignore new line character
}
printf("Length of your input is %d characters.\n", inputLen);
if (inputLen > 0) {
midChar = input[inputLen / 2]; // take right of middle for even number
}
printf("%c\n", midChar);
return 0;
}
In your previous post you used sizeof(input) which is not recommended for reasons described in this post. It is better practice to hold the length of the array in a separate variable, here bufferLen.
Also the use of global variables here input inputLen midChar is generally discouraged as they lead to unexpected behaviour during linking and make program flow harder to understand.
I initialised the memory for the buffer dynamically so the bufferLen could be changed in the program.
When computing the length of the input one must consider the newline character \n which is retained if a small enough string is entered but not if the entered string exceeds the bufferLen.
For strings with even lengths I arbitrarily took the character to the right. The inputLen zero case is also handled.
This whole answer is only an addition to the first one which already found the bug correctly, because I was late to the party.
Other than print char problem, I think there is also a problem at where you indicated.
ex. if input string is abc, inputLen will be 3, midchar index should be at 1 since array index in C start from 0. However ((inputLen+1)/2)+1 gives 3. This probably won't directly cause the segfault but will give wrong answer.
You can replace
if((inputLen % 2) == 0) {
midChar = input[(inputLen/2)+1]; // >>> PROBLEM HERE <<<
}
else {
midChar = input[((inputLen+1)/2)+1]; // >>> PROBLEM HERE <<<
}
with
midChar = input[inputLen/2];
since C will truncate when doing integer division.
a b c -> 3/2 = 1
[0] [1] [2]
a b c d -> 4/2 = 2
[0] [1] [2] [3]
Other than that, you also need to make sure the inputLen is not 0
Although "pretty lady" (#LightnessRasesInOrbit) up here is correct, let me explain what is happening when you do this:
printf("%s\n", charVar);
or this:
printf("%s\n", intVar);
or this:
printf("%s\n", floatVar);
Or when you print things using pritnf() with %s. You have to understand how does printf ("%s", string) work!! So when printf gets %s it looks for C string or in other words, character array terminated with '\0'. If it does not '\0' it will segfault. In depth, printf() works like this:
char name[4];
printf("Hello ", name);
now printf does following:
gets the size of 1st variable ("Hello")
gets the size of 2nd variable (name) How? Simple by this loop:
int varSize;
for (varSize = 0; varSize != '\0'; ++varSize);
moves "Hello" into buffer
Determine the size of second parameter. How, by doing this:
does following
if ("%d")
// read intVar and attach it to the buffer
if ("%f")
// read floatVar and attach it to the buffer
if ("%s")
for (int i = 0; stringVar[i] != '\0'; ++i)
// push each char into the buffer
So I hope you see what is happening if one of for() loops does not find '\0' character. If you do good if you don't well it continues reading through until it segfaults.
NOTE:
This is oversimplified pseudo code on how printf() works and is not actual implementation, this is only for OP to understand what is going on.

Problems with STRCPY and STRCMP when finding the smallest and largest problems

I'm writing a program to find the smallest and largest word according to the dictionary order in K.N.King's problem. Find the largest and smallest of a word until the user inputs a 4 letter word.
Firstly, I use strcmp to compare the input word with the largest or smallest. then using strcpy to copy the input string to the largest or smallest.
#include <string.h>
#include <stdio.h>
main()
{
char inputStr[20] ;
char max[20];
char min[20];
int length =0;
do
{
printf("pls, input your string: ");
gets(inputStr);
if(strcmp(inputStr,max) > 0)
strcpy(max,inputStr);
if (strcmp(inputStr,min) < 0)
strcpy(min,inputStr);
length = strlen(inputStr);
}
while (length != 4);
printf("largest word is: %s\n",max);
printf("smallest word is: %s",min);
}
for example.
Enter Word : Cat
Enter Word : Dog
Enter Word : penguin
Enter Word : bear
the smallest word is bear
the largest word is penguin
However, when running programs, the largest word is always a special character, and the smallest is always right. My program shows the result that
the largest word is:
the smallest word is: bear
You don't asctually initialise max or min so they will be set to arbitrary values when you first compare them.
You can fix this by simply doing setting them to the first word regardless of the comparison:
int firstTime = 1;
do
{
printf("Please input your string: ");
gets(inputStr);
if (firstTime || (strcmp(inputStr, max) > 0))
strcpy(max, inputStr);
if (firstTime || (strcmp(inputStr, min) < 0))
strcpy(min, inputStr);
firstTime = 0;
length = strlen(inputStr);
}
And, as an aside, there's a reason why gets was deprecated and later removed from the standard, there is no way to protect against buffer overflow if you use this function. Further details can be found here, which also includes a very handy solution to the problem.
I suspect the main issue is that either max or min will always be the incorrect, as they are empty (or filled with garbage) to begin with. You should reformat your code to be in the style:
min = max = initial-input()
length = len(min)
while (length != 4)
do stuff
I also recommend using fgets() or getline() for reading input, just in case you decide to put in 100 characters when you only set aside space for 20. Same with strcpy(), it should be replaced by strncpy() just in case. So the result will look something like:
...
fgets(inputStr, 20, stdin);
strncpy(max, inputStr, 20);
strncpy(min, inputStr, 20);
length = strlen(inputStr);
while(length != 4) {
...
}
The problem is due to uninitialized char array. This(using it in strcmp) is undefined behavior. Also logically your code won't work properly. strcasecmp is not part of standard - it is a POSIX thing.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXLETTER 20
int main(void)
{
char inputStr[MAXLETTER] ;
char max[MAXLETTER];
char min[MAXLETTER];
size_t length =0;
bool flag = true;
do
{
printf("pls, input your string: ");
if( fgets(inputStr,sizeof inputStr,stdin) == NULL){
fprintf(stderr, "%s\n", "Error in input");
exit(1);
}
inputStr[strcspn(inputStr,"\n")]='\0';
if(flag){
strncpy(max,inputStr,MAXLETTER-1);
strncpy(min,inputStr,MAXLETTER-1);
max[MAXLETTER-1]=0;
min[MAXLETTER-1]=0;
flag = false;
}
if(strcasecmp(inputStr,max) > 0){
strncpy(max,inputStr,MAXLETTER-1);
max[MAXLETTER-1]=0;
}
if (strcasecmp(inputStr,min) < 0){
strncpy(min,inputStr,MAXLETTER-1);
min[MAXLETTER-1]=0;
}
length = strlen(inputStr);
}
while (length != 4);
printf("largest word is: %s\n",max);
printf("smallest word is: %s",min);
return 0;
}
Compile your program using gcc -Wall -Wextra -Werror progname.c, it will tell you where you are going wrong.
One thing, Don't use gets().
I'm wrong because I don't initialize max and min. However, the program still runs with min...
The thing it is called Undefined behavior. It may work some time and
may not. That's the thing about it. Without initializzing when you
compare then behavior is not defined. It may get some error , may
suprisingly give correct result.
Revised
#include <stdio.h>
#include <string.h>
#define N 20
int main( void )
{
char max[N];
char min[N];
char (*ch)[N];
char inputStr[N] ;
int length = 0;
fgets(inputStr, sizeof(inputStr), stdin);
// Technique from https://stackoverflow.com/a/28462221/701302
inputStr[strcspn(inputStr, "\n")] = 0;
// Set both max and min to initial input in order to ...
strcpy(max,inputStr);
strcpy(min,inputStr);
do
{
fgets(inputStr, sizeof(inputStr), stdin);
inputStr[strcspn(inputStr, "\n")] = 0;
// ... now have basis for valid comparison
if (strcmp(inputStr,max) > 0){
strcpy(max,inputStr);
}
else
if ( strcmp(inputStr,min) < 0){
strcpy(min,inputStr);
}
length = strlen(inputStr);
} while (length != 4);
printf("largest word is: %s\n",max);
ch = &min;
if (strcmp(ch,"") == 0){
ch = "[empty string]";
}
printf("smallest word is: %s",ch);
}
See live code.
Note: it is much safer to use fgets() than gets(). The reason gets() is dangerous is b/c of potential buffer overflows per this article. However, with fgets() the input may terminate with a newline so you need to get rid of it. Although you may use strtok() for that even tho' it wasn't designed with that possibility in mind, as chux remarks it is inadequate if the user's input consists of a newline character.
I revised this answer again, taking a cue from here. The technique utilizes strcspn() which returns the number of characters in str1 not in str2, So, the newline gets replaced every time whether the input consists of one or more printable characters or a newline. I accordingly revised both the code and input at ideaone.com. So, now the output reflects the largest word is penguin and the smallest word is the empty string. But, if you run the code using only the original input of the OP, then the result will be penguin and bear as respectively the largest and smallest words lexicographically speaking.

Is it possible to get the number of elements currently stored in an array in C?

I know it's possible to use the sizeof function to get the size, but it doesn't get a true count of the array length. If I set an array of int 50 and I stored only 10 numbers in there, I would want to get 10 as the number of elements, but of course that won't happen. I know this is definitely a trivial question, but bear with me here and help me on this if it is possible.
My code so far takes an entire sentence and stores it in an array.
#include <stdio.h>
#include <string.h>
int main()
{
int i=0;
char array[50]={0};
fgets(array, 50, stdin);
int len = sizeof(array); // it doesn't work :((((((
for(i=0; i<len; i++)
{
printf("%c\n", array[i]);
}
return 0;
}
As you guys can see, if the user decides to only enter a word of lets say "Bobby Foo" then I would want len number of 9 including the space, but the sizeof function only gets length of the size of the array declared which is 50.. >.>..
Q: Is it possible to get the number of elements currently stored in an array in C?
Short answer: No. You need to track this information yourself.
You happen to be using fgets() with a character array. Since in this case you're getting a C "string", you can use the C function strlen().
It's worth noting that fgets() will also return a newline - so your string might be a one (Mac, Linux) or two (DOS/Windows) characters longer than you expect.
PS:
Here is a bit more about C strings, including the concept of "null termination" (if you're not already familiar with them):
http://www.cprogramming.com/tutorial/c/lesson9.html
Use strlen to get the size of the array. You need to include string.h.
sizeof() is not a function it is an operator. When sizeof is applied to the name of a static array (not allocated through malloc), the result is the size in bytes of the whole array.
If you are using fgets, then you need to remove \n from the string. A simple way would be:
array[strlen(array) - 1] = '\0';
A quick example:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
int main()
{
int i=0;
char array[50]={0};
char *p;
fgets(array, 50, stdin);
//Remove `\n` from the array.
if ((p=strchr(array, '\n')) != NULL)
*p = '\0';
size_t len = strlen(array); // Use strlen to find the length of string
for(i=0; i<len; i++)
{
printf("%c\n", array[i]);
}
return 0;
}

How to correctly input a string in C

I am currently learning C, and so I wanted to make a program that asks the user to input a string and to output the number of characters that were entered, the code compiles fine, when I enter just 1 character it does fine, but when I enter 2 or more characters, no matter what number of character I enter, it will always say there is just one character and crashes after that. This is my code and I can't figure out what is wrong.
int main(void)
{
int siz;
char i[] = "";
printf("Enter a string.\n");
scanf("%s", i);
siz = sizeof(i)/sizeof(char);
printf("%d", siz);
getch();
return 0;
}
I am currently learning to program, so if there is a way to do it using the same scanf() function I will appreciate that since I haven't learned how to use any other function and probably won't understand how it works.
Please, FORGET that scanf exists. The problem you are running into, whilst caused mostly by your understandable inexperience, will continue to BITE you even when you have experience - until you stop.
Here is why:
scanf will read the input, and put the result in the char buffer you provided. However, it will make no check to make sure there is enough space. If it needs more space than you provided, it will overwrite other memory locations - often with disastrous consequences.
A safer method uses fgets - this is a function that does broadly the same thing as scanf, but it will only read in as many characters as you created space for (or: as you say you created space for).
Other observation: sizeof can only evaluate the size known at compile time : the number of bytes taken by a primitive type (int, double, etc) or size of a fixed array (like int i[100];). It cannot be used to determine the size during the program (if the "size" is a thing that changes).
Your program would look like this:
#include <stdio.h>
#include <string.h>
#define BUFLEN 100 // your buffer length
int main(void) // <<< for correctness, include 'void'
{
int siz;
char i[BUFLEN]; // <<< now you have space for a 99 character string plus the '\0'
printf("Enter a string.\n");
fgets(i, BUFLEN, stdin); // read the input, copy the first BUFLEN characters to i
siz = sizeof(i)/sizeof(char); // it turns out that this will give you the answer BUFLEN
// probably not what you wanted. 'sizeof' gives size of array in
// this case, not size of string
// also not
siz = strlen(i) - 1; // strlen is a function that is declared in string.h
// it produces the string length
// subtract 1 if you don't want to count \n
printf("The string length is %d\n", siz); // don't just print the number, say what it is
// and end with a newline: \n
printf("hit <return> to exit program\n"); // tell user what to do next!
getc(stdin);
return 0;
}
I hope this helps.
update you asked the reasonable follow-up question: "how do I know the string was too long".
See this code snippet for inspiration:
#include <stdio.h>
#include <string.h>
#define N 50
int main(void) {
char a[N];
char *b;
printf("enter a string:\n");
b = fgets(a, N, stdin);
if(b == NULL) {
printf("an error occurred reading input!\n"); // can't think how this would happen...
return 0;
}
if (strlen(a) == N-1 && a[N-2] != '\n') { // used all space, didn't get to end of line
printf("string is too long!\n");
}
else {
printf("The string is %s which is %d characters long\n", a, strlen(a)-1); // all went according to plan
}
}
Remember that when you have space for N characters, the last character (at location N-1) must be a '\0' and since fgets includes the '\n' the largest string you can input is really N-2 characters long.
This line:
char i[] = "";
is equivalent to:
char i[1] = {'\0'};
The array i has only one element, the program crashes because of buffer overflow.
I suggest you using fgets() to replace scanf() like this:
#include <stdio.h>
#define MAX_LEN 1024
int main(void)
{
char line[MAX_LEN];
if (fgets(line, sizeof(line), stdin) != NULL)
printf("%zu\n", strlen(line) - 1);
return 0;
}
The length is decremented by 1 because fgets() would store the new line character at the end.
The problem is here:
char i[] = "";
You are essentially creating a char array with a size of 1 due to setting it equal to "";
Instead, use a buffer with a larger size:
char i[128]; /* You can also malloc space if you desire. */
scanf("%s", i);
See the link below to a similar question if you want to include spaces in your input string. There is also some good input there regarding scanf alternatives.
How do you allow spaces to be entered using scanf?
That's because char i[] = ""; is actually an one element array.
Strings in C are stored as the text which ends with \0 (char of value 0). You should use bigger buffer as others said, for example:
char i[100];
scanf("%s", i);
Then, when calculating length of this string you need to search for the \0 char.
int length = 0;
while (i[length] != '\0')
{
length++;
}
After running this code length contains length of the specified input.
You need to allocate space where it will put the input data. In your program, you can allocate space like:
char i[] = " ";
Which will be ok. But, using malloc is better. Check out the man pages.

Resources