C code:
#include<stdio.h>
#include<string.h>
#define STRINGS 10
#define STR_LEN 20
int main(void)
{
char words[STRINGS][STR_LEN];
char input[STR_LEN];
int i;
int mycount;
for(i = 0;i < STRINGS;++i;)
{
printf("Enter a word (or 0 to quit)\n:");
scanf("%19s", input);
if(input[0] == '0') break;
strncpy(words[i], input, STR_LEN);
mycount++;
}
printf("A total of %d strings were entered!\n",mycount);
}
problem: When I run this code and enter some strings it doesn't print out the amount of strings I entered
enter image description here
You need to initalize mycount to 0.
int mycount =0;
The variable mycount is uninitialized. You then attempt to modify it in the for loop via the ++ operator. So you're reading garbage values and writing garbage values. This explains the output you're getting.
Reading an uninitialized variable invokes undefined behavior. In this case, it manifests as garbage values, but it could just as easily output the expected value or cause a crash.
Initialize this variable at the time it is declared.
int mycount = 0;
Related
I learned in the text book, that there are only a few ways you can initialize an array.
Method one:
int ary[5] = {1,2,3,4,5};
Method two:
int ary[] = {1,2,3,4,5};
But what if I want to input user defined values into the array. Would this code be ok? Can anyone teach me a better way to do this?
#include<stdio.h>
#include<conio.h>
int main()
{
int i, n;
printf("Enter array parameter: \n");
scanf("%d",&n);
int a[n];
int b[n];
for(i=0;i<n;i++)
{
printf("Enter value for array a[%d]: \n",i+1);
scanf("%d",&a[i]);
}
n -= 1;
for(i=0;i<=n;i++)
{
b[i]=a[n-i];
}
printf("Value of array b[] is: \n");
for(i=0;i<=n;i++)
{
printf("%d ",b[i]);
}
for(i=0;i<=n;i++)
{
printf("\narray b[%d] = %d ",i,b[i]);
}
getch();
}
int ary[5] {1,2,3,4,5};
This is not a valid array initialization. It should be
int ary[5] = {1,2,3,4,5};
Note the equal sign.
Other wise your array initialization is valid for C99 and above. Plain c would not allow the use of a variable to initialize the array size.
You have a large number of issue, Undefined Behavior being the most critical:
n -= 1;
for(i=0;i<=n;i++)
{
b[i]=a[n-i];
}
When i == n, you index one beyond the end of your b[] array. All arrays in C are zero-indexed, so your loop limits are 0 <= i < n. By using i<=n you loop one-too-many times.
You fail to check the return of any user-input. Try entering '"one"', or accidentally hitting 'r' instead of 4 and see what happens. You must check the return for every user-input and handle the error. What happens if the user enters 1, 2, 'r', 5? You must also empty stdin of any extraneous characters or they will bite you again on your next input.
Don't use conio.h. That makes your code 100% non-portable. You can use the functions in stdio.h for your needs.
That said, when you need to do repetitive tasks like taking integer input, write a short function to do it. You can write one that takes a pointer to the integer to fill, and a pointer to the prompt to display and returns 0 on success or -1 if the user cancels input by generating a manual EOF with Ctrl+d on Linux or Ctrl+z on windows. You can add a helper-function to empty stdin, e.g.
void empty_stdin (void)
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
int getint (int *n, const char *prompt)
{
int rtn;
for (;;) {
fputs (prompt, stdout);
rtn = scanf ("%d", n);
if (rtn == EOF) {
fputs (" (user canceled input)\n", stderr);
return -1;
}
else if (rtn == 0) {
fputs (" error: invalid integer input.\n", stderr);
empty_stdin();
}
else
break;
}
empty_stdin();
return 0;
}
The rest of your program to read an array in a[] and reverse it in b[] is simply:
int main (void) {
int i = 0, n;
if (getint (&n, "Enter array parameter: ") == -1)
return 0;
int a[n], b[n];
for (i = 0; i < n; i++) {
char buf[128];
sprintf (buf, "enter value for a[%d]: ", i+1);
if (getint (&a[i], buf) == -1)
return 0;
}
for (i = 0; i < n; i++)
b[i] = a[n - 1 - i];
puts ("\nvalue of array b[]:");
for (i = 0; i < n; i++)
printf (" %d", b[i]);
putchar ('\n');
#if defined (_WIN32) || defined (_WIN64)
getchar(); /* hold terminal open on windows - type any char, hit return */
#endif
}
Example Use/Output
All valid inputs:
$ ./bin/getarray
Enter array parameter: 5
enter value for a[1]: 5
enter value for a[2]: 4
enter value for a[3]: 3
enter value for a[4]: 2
enter value for a[5]: 1
value of array b[]:
1 2 3 4 5
Errors in input:
$ ./bin/getarray
Enter array parameter: foo
error: invalid integer input.
Enter array parameter: 5
enter value for a[1]: 5
enter value for a[2]: four
error: invalid integer input.
enter value for a[2]: 4
enter value for a[3]: 3
enter value for a[4]: I'm getting tired of this game...
error: invalid integer input.
enter value for a[4]: 2
enter value for a[5]: 1
value of array b[]:
1 2 3 4 5
User cancels input:
$ ./bin/getarray
Enter array parameter: 5
enter value for a[1]: 5
enter value for a[2]: 4
enter value for a[3]: 3
enter value for a[4]: (user canceled input)
Look things over and let me know if you have further questions.
As someone noted, the first way does not work in C. It is valid C++ though.
The second way int ary[] = {1,2,3,4,5}; works, the array ary is initialized with 5 items at compile time (before you even run the program). The memory is allocated on the stack.
You could also do it like this int ary[6] = {1,2,3,4,5};, where you specify what length you want the array to be. You can then access ary[5] and change it to whatever value you want (by default it is 0).
NOTE: ary[6] is out of bounds, since the array's elements go from 0 to 5.
In your code, you make use of something called Variable Length Arrays (VLAs), and as noted by Wikipedia, they are allocated with automatic storage duration on the stack. This means that when the function where you declared them ends, their life duration also ends (they are local to the function scope you declare them in). To understand why this is important, consider this piece of code:
int *func(int n) {
int v[n]; // variable length array
v[0] = 1;
v[1] = 2;
v[2] = 3;
return v; // this will not work, variable length arrays will be destroyed
// when the function they belong to goes out of scope
}
int main() {
int *v;
v = func(3); // when you will try to access the memory in v, it will be undefined
// behaviour (can seg fault, the memory is not yours anymore)
// print values in v
return 0;
}
To fix this issue, you need to use malloc defined in stdlib.h.
int *func(int n) {
int *v = malloc(sizeof(int) * n); // allocate memory for n elements
v[0] = 1;
v[1] = 2;
v[2] = 3;
return v; // this will now work
}
int main() {
int *v;
v = func(3); // this will work
// print values in v
free(v);
return 0;
}
The reason this works is because memory allocated using malloc is allocated on the heap, meaning it survives the whole duration of the program unless you deallocate it yourself (this means that you need to free the memory at the end using the function free).
Array initializing in C:
int ary[5] {1,2,3,4,5};
This is invalid syntax in c (this is valid in c++).
there is 3 ways to initialize c arrays:
with the curly brackets {} like you did (int ary[] = {1,2,3,4,5};)
iterating on the array elements one by one in for loop and initialize each one of them.
via : memset(void *str, int c, size_t n);, for padding the whole array in the same value. e.g. if i want to initialize the array with 0x0, then, memset call will lokks like: memset(arr, 0x0, sizeof(arr));
Regarding the you code:
for each scanf(..) in the code you have to check and validate scanf("%d",&n);, return/errors and user input in n before make any progress in your code. How you check? see later.
In you situation, it's good to limit the user input n and validating that n in defined range (N_min <= n <= N_max), rather than causing to huge array allocating on the stack in case n was set to maximum value by user!
if(scanf("%d",&n) == EOF){
/*errors ocuured*/
f_invoke_error_handling_rotuine();
}
In f_invoke_error_handling_rotuine(..), you can do what ever your code needs to perform, maybe abort() with error message, maybe setting default values to n...etc.
see reference for memset and scanf in man7.org:
scanf, memset
"Would this code be ok? Can anyone teach me a better way to do this?"
This code is okay from a syntactical perspective (you corrected the wrong initialization), but not portable since you use variable length arrays (VLAs) which might not supported by any implementation (They are provided my compiler extensions) and were only fully compliant to the C99 standard.
A better way to do this, is to use malloc() instead and allocate the memory for the array on the heap.
This also has the advantage that you can resize the array if you want to (make it larger f.e.) and free() the memory for the array when no longer needed.
Related stuff:
Is it a good idea to use C99 VLA compared to malloc/free?
Is there any overhead for using variable-length arrays?
When to use variable length array in C, but when a dynamic allocation?
int i, n;
printf("Enter amount of array elements: \n");
if (scanf("%d",&n) != 1)
{
fputs("Error at input!", stderr);
return EXIT_FAILURE;
}
int* a = malloc ( sizeof(*a) * n );
if (!a)
{
fputs("Error at allocation for a!", stderr);
return EXIT_FAILURE;
}
int* b = malloc ( sizeof(*b) * n );
if (!b)
{
fputs("Error at allocation for b!", stderr);
return EXIT_FAILURE;
}
for (i = 0; i < n; i++)
{
printf("Enter value for array a[%d]: \n", i);
if (scanf("%d", &a[i]) != 1)
{
fprintf(stderr, "Error at input for a[%d]!", i);
return EXIT_FAILURE;
}
}
...
free(a);
free(b);
#include <stdio.h>
#include <string.h>
int main(void) {
const int NUM_VALS = 20;
int i;
int actualInput;
char userString[actualInput][NUM_VALS];
int matchCount = 0;
scanf("%d", &actualInput);
for (i = 0; i < actualInput; ++i) {
scanf("%s", userString[i]);
printf("%s", userString[i]);
}
return 0;
}
Output:
b'hellohi\x80\x07#\xd2\x05#\x9a\x16[\xea\xccp\xa6\x15\xf6\x18+\xbf\x87\x8a#\x14)\x05#\xfe\x7f'b'\x92\x1fk\xb3\xfe\x7f\xfe\x7f\x118\x08\xe8\x03\x0eY\x03k\xb3\xfe\x7f\xfe\x7f\xb2Y{\xe8C}8\r\x8b-u{\x8cx86_64'F-8sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin/usr/sbin:/usr/bin:/sbin:/binsbin:/binTF-88tf8RELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so64-linux-gnu/coreutils/libstdbuf.sols/libstdbuf.soout
I've tried some variations replacing userString[i] with userString in the scanf function. The result is outputting 50,000 inputs of my last string. I don't understand what's happening.
The problem is this sequence of code:
int actualInput;
char userString[actualInput][NUM_VALS];
int matchCount = 0;
scanf("%d", &actualInput);
The first line declares a variable called actualInput but doesn't assign a value to that variable.
The second line declares a variable length array (VLA) using the value in actualInput. Using the value of an uninitialized variable results in undefined behavior, which basically means that after that point in the code, anything can happen. What's likely happening (based on your description of the problem) is that actualInput is either zero, or a small number, so you get an array that's too small to hold your input.
The last line (with the scanf) finally assigns a value to actualInput. You may be thinking that the array will resize itself when actualInput is changed. That definitely does not happen. In C, after a VLA is created, its size cannot be changed.
The solution is simple, rearrange the code so that things are done in the proper order:
int actualInput;
scanf("%d", &actualInput);
char userString[actualInput][NUM_VALS];
int matchCount = 0;
As a side note, you should really do some error checking to make sure that the user inputs a reasonable number, before using that number to create an array. For example
int actualInput;
if (scanf("%d", &actualInput) != 1 || actualInput < 1 || actualInput > 1000)
{
printf("That is not a valid array size\n");
return 1;
}
char userString[actualInput][NUM_VALS];
you cant declare it as a 2D array then treat it as a normal array .
each case should include only one letter but it can't be done automatically , I suggest you add this :
for (i = 0; i < actualInput; ++i)
{
gets(stri);
for (k=0;k<strlen(stri);k++)
userString[i][j]=stri[j];
}
So I was working on an assignment for school, and had written up a variation of this code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX 100
// This program takes an input of strings and prints them out with a new line separating each one.
int main() {
char *WordArray[MAX]; //initializing variables
int i = 0;
int count = 0;
printf("enter up to 100 words, that are 20 characters maximum \n");
for (i = 0; i <100; i++){ //runs while there's less than 100 inputs
char Array[1];
scanf("%s",Array); //stores string in the array
if (strcmp(Array, "STOP") == 0) { //compares the string with stop, and if it is, it breaks out of the loop
break;
}
WordArray[i]=Array; //stores the string in the pointer array
}
printf("The output is\n");
for (count = 0; count<i; count++){ //counts up to the amount of words stored
printf("%s\n",WordArray[count]); //outputs each pointer string
}
}
and I noticed that the output was printing "STOP" instead of the values stored. Anyone have any answers to why and/or how to fix it? I know one of the methods is to switch to a 2D array instead of using pointers, but I'm still baffled as to why a program like this wouldn't work.
Your char Array[1]; isn't large enough to store any but an empty string. Also, when it works, every pointer will point to the same string, which will be the last entry you made. This makes some corrections where commented.
#include <stdio.h>
#include <stdlib.h> // instead of ctype.h
#include <string.h>
#define MAX 100
// This program takes an input of strings and prints them out with a new line separating each one.
int main() {
char *WordArray[MAX];
int i = 0;
int count = 0;
printf("enter up to 100 words, that are 20 characters maximum \n");
for (i = 0; i <100; i++){
char Array[21]; // increase size of array
scanf("%20s",Array); // limit entry length
if (strcmp(Array, "STOP") == 0) {
break;
}
WordArray[i] = strdup(Array); // allocate memory for and copy string
}
printf("The output is\n");
for (count = 0; count<i; count++){
printf("%s\n",WordArray[count]);
}
// free each string's memory
for (count = 0; count<i; count++){
free(WordArray[count]);
}
}
Program output:
enter up to 100 words, that are 20 characters maximum
one two three STOP
The output is
one
two
three
Edit: note that your code contains another undefined behaviour besides the too-short string char Array[1] which is that you dereference the pointer you stored in char *WordArray[MAX];. The scope of Array is inside the for loop, and theoretically ceases to exist after the loop completes, so the pointer you store is invalid. Here, the word entered is duplicated with strdup so that doesn't apply.
I got a quick question. Is it possible to 'randomize' the output I get? For example in the first run I get 'Magic number 1', and when I run it again, I could get 'Magic number 3'. I couldn't find any help elsewhere.
#include <stdio.h>
int main() {
char *a = "Magic number 1\n";
char *b = "Magic number 2\n";
char *c = "Magic number 3\n";
printf("%s", b);
return 0;
}
I tried to edit the code to
printf("%s", a||b);
But || is used only to logic, right?
|| produces an int either 1 or 0 based on the truth of the logical OR statement.
What is happening in the statement printf("%s", a||b); is that the value 1 (since the addresses of the string pointers being compared are non-zero, thus the OR is true and returns 1) is attempted to be accessed as the pointer to a null-terminated string. This is undefined behavior, and very likely going to crash (if you're lucky).
If you want to print a random string from a set of variables in your code, what you can do is:
#include <stdlib.h>
#include <time.h>
// (in main())
srand((unsigned)time(NULL));
int r = rand()%3;
if(r == 0)
puts(a);
else if(r == 1)
puts(b);
else
puts(c);
What about something like this?
Instead of creating seperate variables for each of them, you can use 2D arrays.
int main() {
char arr[3][100] = {"Magic number 1\n", "Magic number 2\n", "Magic number 3\n"};
int i, range=3;
srand((unsigned)time(NULL));
i = rand()%range;
puts(arr[i]);
return 0;
}
This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 4 years ago.
I cannot retrieve string using printf . instead getting error : segmentation fault
int main(){
char * a[5];
int i;
printf("\n enter value ");
for (i=0;i<5;i++){
printf("%d Name :\n",i);
scanf("%s",&a[i]);
}
printf("%s",a[2]);
printf("%s",a[3]);
}
~
char * a[5]; is array of 5 char pointer that means you can store 5 char buffer of any length.
The problem is in the statement
scanf("%s",&a[i]); replace this with scanf("%s",a[i]);
case 1 :-
int main(){
char *a[5] = {"stackoverflow","meta","ask ubuntu","super","unix"};
/* here a[row] can have any number of char */
for (int i = 0 ;i < 5;i++) {
printf("%s\n",a[i]);
}
return 0;
}
Case 2 :-
int main(){
char *a[5];
for (int i=0;i<5;i++){
printf("%d Name :\n",i);
a[i] = malloc(MAX);/* define MAX how many char you want to store into that */
scanf("%s",a[i]); /* & not required as a[i] itself address */
}
for (int i = 0 ;i < 5;i++) {
printf("%s\n",a[i]);
}
/* don't forget to free once job is done */
for (int i = 0 ;i < 5;i++) {
free(a[i]);
}
return 0;
}
You shouldn't input to a char* .
And you shouldn't store any string by char*, including string literal, in fact, string literal convert to char* is deprecated many years ago.
Use char a[5][MaximumLength] instead. MaximumLength should be a literal.
The problem is you are using a pointer before it has been initialized. It does not yet point at valid memory. These leads to program crashes or other kinds of unexpected behavior, such as "segmentation faults".
So you should edit it to:
char* my_string = malloc(size+1);
The %c format specifier is used whenever we want to be specific that the variable that we are going to printf or scanf is of type char.
On the other hand the %s format specifier is used to specify to the printf or scanf functions that contents of the address that is specified as the next parameter are to considered as string.
You are taking char as input, not the whole string.
scanf("%s",&a[i]);, will be scanf("%c",&a[i]);
printf("%s",a[3]);, will be printf("%c",a[3]);
printf("%s",a[2]);, will be printf("%c",a[2]);
The following code worked fine:
#include<stdio.h>
#include<stdlib.h>
int main(){
char* a = malloc(size+1); // where size is max string length
int i;
printf("\n enter value ");
for (i=0;i<5;i++){
printf("%d Name :\n",i);
scanf("%c",&a[i]);
printf("%c\n",a[i]);
}
printf("%c\n",a[2]);
printf("%c\n",a[3]);
free(a);
}