Segmentation error while working with strings - c

Given a string, num, consisting of alphabets and digits, find the frequency of each digit(0-9) in the given string.
'''
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include<ctype.h>
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
char num[20];
int i;
int count[15]={0};
scanf("%s",num);
for(i=0;i<10;i++){
printf("\n");
for(int j=0;j<strlen(num);j++){
if(isdigit(num[j])){
if(i == num[j]-'0'){
count[i]+=1;
}
}
}
printf("\nCount %d:%d",i,count[i]);
}
for(i=0;i<10;i++){
printf("%d ",count[i]);
}
return 0;
}
'''
OUTPUT:
Count 0:5
Count 1:9
Count 2:5
Count 3:12
Count 4:8
Count 5:11
Count 6:15
Count 7:4
Count 8:4
exited, segmentation fault
Why is it not working when checking if the digit is 9?

When looking at your output, it seems that you have entered a string much longer than 19 characters. So your program has undefined behavior.
This
scanf("%s",num);
is something that you should never do. Remember to limit the input to the size of your buffer. That is:
char num[20]; // Size of buffer is 20
scanf("%19s",num);
^^
At max allow 19 characters so that there is also room for the string termination
Or - perhaps better - use fgets instead of scanf. One benefit of fgets is that it takes the buffer size as argument - consequently you never forget to specify it.
Also notice that your outer for loop is unnecessary. You can update the array directly using a single loop.
// for(i=0;i<10;i++){ Delete this - it's not needed
for(int j=0;j<strlen(num);j++)
{
if(isdigit(num[j]))
{
count[num[j]-'0']+=1; // Update array
}
}
BTW: You only need 10 elements in the counter, i.e.
int count[15]={0}; ---> int count[10]={0};

Related

Weird result from random character generator in C

I am trying to write a program in C that spits out random characters. Following instructions I found here, I wrote this program.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srandom((unsigned) time(NULL));
printf("Tests various aspects of random\n");
char misc;
int num, index;
printf("Enter number of chars: ");
scanf("%d", &num);
printf("\n");
for (int i = 0; i < num; i++) {
index = random() % 26;
misc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[index];
printf("%d:%s\n", index, &misc);
}
}
However, it doesn't behave as I expect. When entering a small number of characters for it to generate, like 10, it makes the expected output.
My expected output is a set of
rand_int:char
pairs printed to the screen.
Here is an example of normal operation
Tests various aspects of random
Enter number of chars:
7:H
4:E
23:X
2:C
4:E
17:R
22:W
11:L
9:J
4:E
However, if I input a large value such as 100, it outputs very strange things like:
Tests various aspects of random
Enter number of chars:
18:Sd
3:Dd
21:Vd
10:Kd
19:Td
19:Td
14:Od
7:Hd
15:Pd
22:Wd
24:Yd
22:Wd
12:Md
[rest omitted for brevity...]
So the question is, why does it behave this way?
What might be a better approach to avoid this?
The comments made by Jabberwocky and Federico klez Culloca got it right.
I was trying to print the character as a string. This was wrong and did weird things.
I needed to use:
printf("%d:%c\n", index, misc);
instead of
printf("%d:%s\n", index, &misc);
All is very simple. The program has undefined behavior. You are using the format string %s that is used to output strings.
printf("%d:%s\n", index, &misc);
However the variable misc is not a character array that contains a string. It is just a single character. So the function printf outputs all characters beyond the variable misc until a zero-terminating character is encountered.
And it seems that the variable num is allocated next to the variable misc. So the printf call outputs also bytes of the variable num that contains the value 100. If to output this value stored in a byte as an ASCII character then you will get the character 'd'.
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
char c = 100;
putchar( c );
putchar( '\n' );
return 0;
}
Its output is
d
Instead of the format %s use the format %c in the printf call. For example
printf("%d:%c\n", index, misc);

trying to get user input, put the input into a array then clear the input so it can get more

so im trying to get input from a user then put the input into a array and then clear the input so it can get more but all i get is these weird symbols here is my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char source[] = "this is the source string";
int main()
{
char people[5][260];
char input[260];
int i, l;
printf("please enter 5 names\n");
for(i=1;i<6;i++)
{
gets(input);
strcpy(people[1], input);
input[260] = '\0';
}
for(l=0;l<6;l++)
printf("%s\n", people[l]);
}
}
Change
for(i=1;i<6;i++)
{
gets(input);
strcpy(people[1], input);
input[260] = '\0';
}
to
for(i=0;i<5;i++)
{
gets(input);
strcpy(people[i], input);
input[0] = '\0';
}
Now to be clear i changed the loop from 0 to 5 instead of 1 to 6 because
array indices start from 0.
In the strcpy function call you passed the same value again and again which is 1, I changed it to the loop variable i, which is the correct way.
In your code snippet you assigned the value of input[260] = '\0' which is also wrong.
'\0' is used to denote the end of a string
so as you have to empty your character array so
'\0' should be assigned to the first index of the array to denote that
the array is empty.
Now in the second loop, since you have stored 5 names so the loop should be from i=0 to i<5 instead of i<6
So change
for(l=0;l<6;l++)
printf("%s\n", people[l]);
to
for(l=0;l<5;l++)
printf("%s\n", people[l]);
And also you used an extra curly brace after the last printf statement. Remove it and your code is fixed.
Since you have used the return type of the main function as int
int main()
So it would return an integer value, so
you should use a return statement
before the last curly brace like this
return 0;
You have declared a character array named source[] with a global scope but you haven't used it anywhere in your code so it's better if you remove it.
And also properly
indent your code using white spaces and tabs to make it understandable
and readable
, with code indentation your code will be more readable and you won't miss any curly brace or use extra ones like you used in your code.
To sum up your new code will look like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char people[5][260];
char input[260];
int i, l;
printf("please enter 5 names\n");
for(i=0;i<5;i++)
{
gets(input);
strcpy(people[i], input);
input[0] = '\0';
}
for(l=0;l<5;l++)
printf("%s\n", people[l]);
return 0;
}
The first for loop should go from 0 to 5, not 1 to 6.
Pretty sure you meant to put i in the brackets here, not 1:
strcpy(people[1], input);
Don't use gets or strcpy; they're insecure. Use fgets and strlcpy or strncpy instead.
input[260] should be input[259]; element 260 is out of bounds.
Set input[259] to zero before you copy the string, not after.
The second loop goes from 0 to 6. Again it should go from 0 to 5, since 5 is the maximum allowed index of an array of size 6.

Array of "strings" in C

I know that there is a question with the same name, but it didn't work for me.
I'm making a home-compiler, returns the words that belongs to a language.
The words to analyze are in this vector:
char *cadenas[]= {"123", "4567L", "5a23", '\0'};
Now I want to enter the words by console, but strings can't be used in C, how can I do it? (Without making a matrix possibly)
void getCadenas(char *cadenas[]){
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
char cadena[15];
gets(cadena);
int x=0;
while(cadena[0]!='z'){
strcpy(cadenas[x],cadena);
x++;
gets(cadena);
}
}
If I understand your problem correctly, you would like the user to be able to enter multiple strings, until he/she types z
See if this piece of code helps you out. The strings will be stored in the cadenas array, as requested.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define MAX_CADENAS 100
#define MAX_CADENA_LEN 255
int getCadenas(char **cadenas){
int x=0;
char cad[MAX_CADENA_LEN+1];
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
while(x<MAX_CADENAS) {
scanf("%s", cad);
if (strcmp(cad,"z")==0)
break;
cadenas[x] = malloc(strlen(cad)+1);
strcpy(cadenas[x], cad);
x++;
}
return x;
}
char *cadenas[MAX_CADENAS];
int main() {
int num, i;
num = getCadenas(cadenas);
for (i=0;i<num; i++) {
printf("%s\n", cadenas[i]);
}
}
Note0: the code assumes you know in advance what the maximum number of input strings can be (100). It also assumes a maximum size for each input string (255 characters)
Note1: gets is deprecated. Also, instead of scanf, you might want to use fgets.
Note2: the present code is for illustrative purpose only. It allocates memory for each input string, but it assumes no error occurs in doing so (i.e. it does not check what malloc returns).
Note3: the allocated memory blocks must be freed when not used anymore (hint: cycle through the cadenas array and use free)
Assuming you don't mind carrying on with fixed-size strings and arrays, here is your original program modified:
#include <stdio.h>
#include <string.h>
#define MAX_CADENAS 100
#define CADENA_LIMIT 1000
// ...
void getCadenas(char cadenas[MAX_CADENAS][CADENA_LIMIT]){
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
int x;
for(x=0; x<MAX_CADENAS-1; x++){
char cadena[CADENA_LIMIT];
fgets(cadena, CADENA_LIMIT, stdin);
// fgets will copy the newline character, we don't want that
int cadenaLength=strlen(cadena);
if(cadena[cadenaLength-1]=='\n')
cadena[cadenaLength-1]='\0';
if(strcmp(cadena, "z")==0) break;
strcpy(cadenas[x], cadena);
}
cadenas[x][0]='\0';
}
// ...
Prefer fgets as you can prevent overflow of the fixed-size strings. Unfortunately it copies the newline as well, so I have code to handle that. The result is an array in the form you originally specified (except it ends with "" which we decided was what you were after in the comments).
You can read arbitrary sized strings in C like in other languages, but you would need to implement it with malloc() and co. Allocating dynamically sized memory is primarily controlled with the functions malloc, calloc, realloc and free. This would make the program unavoidably more complicated. Here is one way of doing this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ...
char *getCadena(){
int length=0, capacity=1, character;
char *cadena=malloc(1); // sizeof(char) is always 1
while((character=getchar())!=EOF){
if(character=='\n') break;
// Add character to string
length++;
if(capacity<length){
capacity*=2;
cadena=realloc(cadena,capacity);
}
cadena[length-1]=character;
}
// Add terminator to cadena
length++;
if(capacity<length){
capacity*=2;
cadena=realloc(cadena,capacity);
}
cadena[length-1]='\0';
return cadena;
}
char **getCadenas(){
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
int length=0, capacity=1;
char **cadenas=malloc(sizeof(char *));
for(;;){
char *cadena=getCadena();
if(strcmp(cadena,"z")==0){
free(cadena);
break;
}
// Add pointer to cadenas array
length++;
if(capacity<length){
capacity*=2;
cadenas=realloc(cadenas,capacity*sizeof(char *));
}
cadenas[length-1]=cadena;
}
// Add NULL to end of cadenas
length++;
if(capacity<length){
capacity*=2;
cadenas=realloc(cadenas,capacity*sizeof(char *));
}
cadenas[length-1]=NULL;
return cadenas;
}
void freeCadenas(char **cadenas){
int i=0;
while(cadenas[i]!=NULL){
free(cadenas[i]);
i++;
}
free(cadenas);
}
// ...
This works mostly the same as the previous function, except you should use freeCadenas eventually, and I end the array with NULL instead of "" which is customary.
The code is a lot longer, but it's pretty typical of more sophisticated C code with less arbitrary limits. In fact real C code usually has more robust handling of errors and more generic functions for managing dynamic arrays. If you actually manage to make this "home-compiler", however, you will figure all this out for yourself.

Program crashes when trying to scan strings into array

I am writing a program to intake exactly 5 peoples last names and their votes. Which will display the names of the people entered, the corresponding votes, and also the winner.
I need the names of the people into one array of strings. That is where the program crashes. Not sure if I can modify this to make it work or if I need to redo it.
the malloc function seems to be a recurring fix for this type of problem ?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int TotalVotes(int voteArray[],int size)
{
int Sum=0;
for (int i=0;i<size;i++)
{
Sum+=voteArray[i];
}
return Sum;
}
int Winner(int voteArray[],int size)
{
int max;
max=0;
if (voteArray[1]>voteArray[max])
max=1;
if (voteArray[2]>voteArray[max])
max=2;
if (voteArray[3]>voteArray[max])
max=3;
if (voteArray[4]>voteArray[max])
max=4;
return max;
}
void main()
{
char nameArray[5];
int voteArray[5],Total,winner;
for (int i=0;i<5;i++)
{
voteArray[i]=0;
}
for (int j=0;j<5;j++)
{
printf("Enter the name of the candidate number %d\n",j+1);
scanf("%s",nameArray[j]);
printf("Enter that persons number of votes\n");
scanf("%d",&voteArray[j]);
}
Total=TotalVotes(voteArray,5);
winner=Winner(voteArray,5);
printf("%s\t%s\t%s\n","Candidate","Votes Received","% of Total Votes");
for (int y=0;y<5;y++)
{
printf("%s\t%d\t%0.2f\n",nameArray[y],voteArray[y],(float)voteArray[y]/Total);
}
printf("The Winner of The Election is %s\n",nameArray[winner]);
}
char nameArray[5]; is should be like char nameArray[5][20];
Yeah, in C, strings are represented by character arrays (char* or char[]).
Also, you should get fgets instead of scanf with strings for two reasons:
Fgets helps prevent buffer overflow because it knows the size of the string in advance.
Fgets will always run because it does not leave characters in the input buffer like scanf does.
The prototype for fgets looks somewhat like this (you can use stdin for the FILE pointer to read in from the keyboard, but realize that fgets keeps newlines):
fgets( char *output_variable, unsigned int string_length, FILE *input_file );
Also, if you use scanf, you should do a lot more error checking for invalid input.

Heading the right way on c matrix code?

My instructor said the way to start this is to use the getline() function from out book, then get the numbers from the line, then have those numbers in matrix form, I do not understand why I would use getline?
//eventually this code should take in a square matrix and from 2x2 to 6x6
//the plan is to get it to read in a line, then get the numbers from the line,
//then print out the numbers in a matrix form. That is the goal for today.
//later I will try to get the actual matrix part working
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//error list for error checking will need later I guess (from my notes)
#define ENDOFFILE -1
#define TOOMANYNUMS -2
#define LIMIT 256
//functions declared
int get_line(char line[], int);
//main
main(){
char line[255];
int num[6];
printf("Please input numbers %c: ", line);
get_line(line,LIMIT);
}
//functions
int get_line(char s[],int lim){
int c, i;
for (i=0;i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if(c=='\n'){
s[i]=c;
++i;
}
s[i]='\0';
return i;
}
The getline(char[], int) function reads characters from the console with getchar() and stores them in the array s[]. The array s[] points at the same memory as the line[] array in the main() function.
getline is not just returning the lenth of the line, it's also copying the first line into the s parameter. So after your call of getline(line,LIMIT) (which doesn't btw, store the return value anywhere), the line variable will contain the first line.
Edit: I should also point out that your printf just above the call to getline is referencing the line variable, which is uninitialized and a char array, not a single character

Resources