Segmentation fault (core dumped) programming in C - c

I was solving the HackerRank problem given here : -- https://www.hackerrank.com/challenges/bigger-is-greater
Program statement is as follow :
Given a word, rearrange the letters to construct another word in such a way that is lexicographically greater than original one. In case of multiple possible answers, find the lexicographically smallest one among them.
If you don't understand then just go to the link; they have explained with examples.
I made the program as given below. In this program I have made two dimensional array. And variable t decides number of row and number is fix.
Code is running as it should be when t = 1.
But when t is greater than 1 or some large number it gives error segmentation error
Code is as below :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int i,j,n,rot;
int t;
scanf("%d",&t);
char c[t][100];
char temp;
for(int i=0;i<t;i++)
{
scanf(" %s",c[i]);
}
rot=t;
for(int t=0;t<rot;t++)
{
n = strlen(c[t]);
//printf("%d\n",n);
for(i=n-1;i>=0;i--)
{
for(j=i-1;j>=0;j--)
{
//printf("comparint %c and %c\n",c[t][i],c[t][j]); //FOR DEBUG
if(c[t][i]>c[t][j]) goto gotit;
}
}
printf("no answer\n");
continue;
gotit:
temp = c[t][i];
c[t][i]=c[t][j];
c[t][j]=temp;
n = (n-1)-j;
//printf("%s\n",c[t]); //FOR DEBUG
//printf("%d %d %d\n",i,j,n); //FOR DEBUG
for(i=0;i<n-1;i++)
{
for(int k=0;k<n-1;k++)
{
// printf("comparint %c and %c\n",c[t][j+k+1],c[t][j+k+2]);
if(c[t][j+k+1]>c[t][j+k+2] )
{
temp = c[t][j+k+1];
c[t][j+k+1]=c[t][j+k+2];
c[t][j+k+2]=temp;
}
}
}
printf("%s\n",c[t]);
}
return 0;
}

t can be 10^5 or 100,000. Your c array is c[t][100], so the size of that is 100000 * 100, which is 10,000,000. You're probably getting a stack overflow.
As WhozCraig pointed out, the processing of each case is independent. Thus, c can be a one dimensional array: char c[100]. Change all c[t][...] into c[...].
Adjust things so that you have one outer loop:
int
main()
{
int t;
char c[100];
scanf("%d", &t);
for (int i = 0; i < t; i++) {
scanf(" %s", c);
// do all processing for this line ...
n = strlen(c);
}
return 0;
}

Related

How to find duplicate letter in array in C

I am making a program which requires the user to input an argument (argv[1]) where the argument is every letter of the alphabet rearranged however the user likes it. Examples of valid input is "YTNSHKVEFXRBAUQZCLWDMIPGJO" and "JTREKYAVOGDXPSNCUIZLFBMWHQ". Examples of invalid input would then be "VCHPRZGJVTLSKFBDQWAXEUYMOI" and "ABCDEFGHIJKLMNOPQRSTUYYYYY" since there are duplicates of 'V' and 'Y' in the respective examples.
What I know so far is, that you can loop through the whole argument like the following
for (int j = 0, n = strlen(argv[1]); j < n; j++)
{
//Place something in here...
}
However, I do not quite know if this would be the right way to go when looking for duplicates? Furthermore, I want the answer to be as simple as possible, right know time and cpu usage is not a priority, so "the best" algorithm is not necessarily the one I am looking for.
Try it.
#include <stdio.h>
#include <stddef.h>
int main()
{
char * input = "ABCC";
/*
*For any character, its value must be locate in 0 ~ 255, so we just
*need to check counter of corresponding index whether greater than zero.
*/
size_t ascii[256] = {0, };
char * cursor = input;
char c = '\0';
while((c=*cursor++))
{
if(ascii[c] == 0)
++ascii[c];
else
{
printf("Find %c has existed.\n", c);
break;
}
}
return 0;
}
assuming that all your letters are capital letters you can use a hash table to make this algorithm work in O(n) time complexity.
#include<stdio.h>
#include<string.h>
int main(int argc, char** argv){
int arr[50]={};
for (int j = 0, n = strlen(argv[1]); j < n; j++)
{
arr[argv[1][j]-'A']++;
}
printf("duplicate letters: ");
for(int i=0;i<'Z'-'A'+1;i++){
if(arr[i]>=2)printf("%c ",i+'A');
}
}
here we make an array arr initialized to zeros. this array will keep count of the occurrences of every letter.
and then we look for letters that appeared 2 or more times those are the duplicated letters.
Also using that same array you can check if all the letters occured at least once to check if it is a permutation
I don't know if this is the type of code that you are looking for, but here's what I did. It looks for the duplicates in the given set of strings.
#include <stdio.h>
#include <stdlib.h>
#define max 50
int main() {
char stringArg[max];
int dupliCount = 0;
printf("Enter A string: ");
scanf("%s",stringArg);
system("cls");
int length = strlen(stringArg);
for(int i=0; i<length; i++){
for(int j=i+1; j<length; j++){
if(stringArg[i] == stringArg[j]){
dupliCount +=1;
}
}
}
if(dupliCount > 0)
printf("Invalid Input");
printf("Valid Input");
}
This code snippet is used to count the duplicate letters in the array.
If you want to remove the letters, Also this code snippet is helpful .Set null when the same characters are in the same letter.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int count=0;
int array[]={'e','d','w','f','b','e'};
for(int i=0;i<array.Lenth;i++)
{
for(int j=1;j<array.Length;j++)
{
if(array[i]==array[j])
{
count++;
}
}
}
printf("The dublicate letter count is : %d",count);
}

ADD elements of an array with a given condition

There is an array of n students( stu[n]).If gender is boy then my code adds
for boy b, 2nd,4th,6th,........even position elements of array and
for girl g, 1st,3rd,5th....odd position elements of array.
1> Gender of boys denoted by b.
2> Gender of girls denoted by g.
Input info>>
The 1st line contains n, denoting the number of students in the class, hence the number of elements in the array.
Each of the subsequent lines contains the marks of n students .
The last line contains gender b/g;
Output info>>
The output should contain the sum of all the alternate elements of marks as explained above.
#include <stdio.h>
int main() {
int n,i;
scanf("%d",&n);//n denotes number of students.
int stu[n],sum=0;
for(i=1;i<=n;++i)
scanf("%d",&stu[i]);//for accepting input in array.
char gen;
scanf("%s",&gen);//for accepting input gender b/g.
for(i=1;i<=n;i++){
if(gen=='g' && i%2!=0){ //girl g adds alternate odd position elements.
sum=sum+stu[i];
printf("%d",sum);
}
else if(gen=='b' && i%2==0){ //boy b adds alternate even position elements.
sum=sum+stu[i];
printf("%d",sum);
}
}
//code
return 0;
}
Sample Input
3
3
2
5
b
Sample Output
8
explanation>>
marks=[3,2,5] and gender = b so it will add 3+5(even position 0,2 alternate elements). If gender in place of b is g then it will produce output = 2.
My code is shows output of 0 in all test cases.
You have the major problem in
int n,i;
int stu[n],sum=0;
here, n being a uninitialized local scoped variable with automatic storage, the initial value is indeterminate.
Now, since the address of the variable was never taken and it has a type that can have trap representation, attempt to use the value (int stu[n]) will invoke undefined behavior.
You need to scan in the value into n first, then use that to define the VLA stu. Something like
int n,i;
scanf("%d",&n);//n denotes number of students.
// **Note: please check for errors in input with scanf return value.**
int stu[n],sum=0; // here, n has the scanned value.
That said,
char gen;
scanf("%s",&gen);
is also horribly wrong, you want to scan in a char, not a string, and with the address of a plain char variable, %s conversion specification would be UB, again. You should use %c and discard any whitespaces which is present in buffer altogether.
You're making things more complicated than they need to be. Here is how you can possibly do:
#include <stdio.h>
int main(void)
{
int mark;
int b = 0;
int g = 0;
char students_marks[5];
for (int i=0; i<5; i++) {
scanf("%d", &mark);
students_marks[i] = mark;
}
for (int i=0; i<5; i++) {
if (i%2 == 0) b += students_marks[i];
if (i%2 == 1) g += students_marks[i];
}
printf("Boys: %d\nGirls: %d\n", b, g);
return 0;
}
You should probably not use an array, and just ignore the first data point. It is (probably) easier to use a linked list. Or maybe just use two lists, alternating the inputs between them. And I would definitely not use scanf. If you are new to C, do NOT waste your time learning the foibles of the scanf format string language. The only time scanf is ever useful is in introductory courses where instructors incorrectly believe that you will be able to get input more quickly than if you spend time learning other methods. But in fact you will end up burning more time learning when to use spaces in the format string that you saved by not learning fread. After your introduction to C, you will (almost) never use scanf. Also, it seems like a horrible design to put the discriminant at the end of the input. The values to be summed (the gender) should be given as a command line argument. That said, you could just do:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
FILE *
xfopen(const char *path, const char *mode)
{
FILE *rv;
if( (rv = fopen(path, mode)) == NULL ) {
perror(path);
exit(EXIT_FAILURE);
}
return rv;
}
int
main(int argc, char **argv)
{
int i;
int size; /* Should probably be size_t. Skipping that for now. */
FILE *in = argc > 1 ? xfopen(argv[1], "r") : stdin;
int sum = 0;
if( fscanf(in, "%d", &size) != 1 || size <= 0 ) {
fprintf( stderr, "invalid input\n" );
exit(EXIT_FAILURE);
}
int grades[size];
for( i = 0; i < size; i++ ) {
if(fscanf(in, "%d", grades + i) != 1) {
fprintf( stderr, "invalid input on line %d\n", i );
exit(EXIT_FAILURE);
}
}
char gender;
if(fscanf(in, " %c", &gender) != 1) {
fprintf( stderr, "invalid input on line %d\n", i );
exit(EXIT_FAILURE);
}
if(strchr("bBgG", gender) == NULL) {
fprintf( stderr, "invalid gender: %c\n", gender);
exit(EXIT_FAILURE);
}
for( i = tolower(gender) == 'b'; i < size; i += 2 ) {
sum += grades[i];
}
printf("sum: %d\n", sum);
}
Hmm… i changed your code a Little bit and hope this runs as described.
int main() {
int n, index, sum=0;
int* stu;
scanf("%d", &n); // input number of studens
if(n>0)
stu = malloc(n*sizeof(int)); // allocate memory
else
return 0;
for(index=0;index<n;index++)
scanf("%d", &stu[index]);
char gen;
scanf("%c", &gen);
for(index=0; index<n; index++){
if(gen=='g' && index%2!=0) {
sum += stu[index];
printf("%d", sum);
} else if(gen=='b' && index%2==0) {
sum += stu[index];
printf("%d", sum);
}
}
return 0;
}

C program to generate pseudolanguage - global 3D array is too large (segmentation fault)?

I am supposed to write a program which prints a text in pseudo-English by parsing an existing English text and looking at the last two letters printed to determine what the next one will probably be (the first to are imagined as '.' and ' '). For that task, I came up with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
short characters[256][256][256];
int main(int argc, char* argv[]){
if(argc<2){
printf("In addition to the input file and maybe output file, please enter the number of output sentences as a command line argument.\n");
return 1;
}
/*Different approach where I malloced the array instead, same result*/
/*short ***characters=malloc(256 * sizeof(short**));
for(int i=0; i<256; i++){
*characters[i]=malloc(256 * sizeof(short*));
for(int i2=0; i2<256; i++){
characters[i][i2]=malloc(256 * sizeof(short**));
}
}*/
/*Read text*/
char a='.', /*pre-previous character*/
b=' ', /*previous character*/
c; /*current character*/
int n=0;
while((c=getchar())!=EOF){
characters[a][b][c]++;
a=b;
b=c;
n++;
}
/*Check how many sentences should be printed*/
int sentences=0, multiplier=1;
for(int i=0; i<sizeof(argv[1])/8; i++){
sentences+=argv[1][i]*multiplier;
multiplier*=10;
}
/*Print text*/
int currentsentences=0, random, p1, p2;
a='.';
b=' ';
while(currentsentences<sentences){
int uninitialized;
srand(time(0)+p1+p2+uninitialized); /*adds a bit of entropy*/
random=rand()%n;
p1=0;
for(int i=0; ; i++){
p2=p1+characters[a][b][i];
if(random>p1 && random<=p2){
c=characters[a][b][i];
p1+=characters[a][b][i];
break;
}
}
putchar(c);
if(c=='.' || c=='?' || c=='!')
currentsentences++;
a=b;
b=c;
}
return 0;
}
It compiles without errors or warnings, however, when I try to run this program, it always returns a segfault before printing anything, unless I do not enter enough command line arguments, in which case it enters the first if clause. This is why I think it has to do something with the 3D array, as it seems not being able to even enter the first loop (if I let it print something before that, it won't). It is needed to be that large, as the structure is the following: [pre-previous letter][previous letter][current letter]=how often did this constellation occur. As I probably would not need higher ASCII and the range of char would probably have been enough, I tried char instead of short and an array of 128*128*128 - same result. Running it as root did not change much and the same goes for increasing ulimit. However, aren't global variabloes saved in the heap? The use of malloc(), which I commented out above, did not change anything as well. I have tried this on two machines, one OS: X, 64 Bit and 8GB DDR3, the other one Linux Mint 19.1, 64 Bit and 32GB DDR4. Both the same result, again (MacOS said segmentation fault: 11, Linux said segmentation fault (core dumped)). As the used memory of that array is about 33 MB, my RAM cannot be the problem either. So why is there a segfault? Do I need to allocate more RAM to the heap (I do not think this is even possible)? Is it maybe something that has not to do with the array and/or its size as all?
This is the latest version of the program; still showing the same behavior:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
short characters[256][256][256];
int main(int argc, char* argv[]){
/*Check if number of sentences was given*/
if(argc<2){
printf("In addition to the input file and maybe output file, please enter the number of output sentences as a command line argument.\n");
return 1;
}
/*Different approach with malloc*/
/*short ***characters=malloc(256 * sizeof(short**));
for(int i=0; i<256; i++){
*characters[i]=malloc(256 * sizeof(short*));
for(int i2=0; i2<256; i++){
characters[i][i2]=malloc(256 * sizeof(short**));
}
}*/
/*Read input text*/
int a='.', /*pre-previous character*/
b=' ', /*previous character*/
c; /*current character*/
int n=0;
for(; (c=getchar())!=EOF; n++){
characters[a][b][c]++;
a=b;
b=c;
}
/*Check how many sentences should be printed*/
int sentences=0, multiplier=1;
for(int i=strlen(argv[1])-1; i>=0; i--){
sentences+=(argv[1][i]-'0')*multiplier;
multiplier*=10;
}
/*Print text*/
int currentsentences=0, random, p1=0, p2=0;
a='.';
b=' ';
srand(time(0));
while(currentsentences<sentences){
random=(rand()+p1+p2)%n;
p1=0;
for(int i=0; i<256; i++){
p2=p1+characters[a][b][i]; /*Determine range for character*/
if(random>p1 && random<=p2){ /*Cheack if random number is in range of character*/
c=characters[a][b][i];
p1+=characters[a][b][i];
break;
}
}
putchar(c);
if(c=='.' || c=='?' || c=='!')
currentsentences++;
a=b;
b=c;
}
return 0;
}
UPDATE: An interesting behavior it shows is that, if you add something like printf(„here“) to the very beginning of the of the program, it will output that „here“ if the first if statement if entered. However, if it is not, the program will return a segfault before printing anything.
UPDATE 2: Interestingly, if you do not give an input file and enter everything manually, it will not return a segfault, but also never finish as well.
UPDATE 3: The program now works, see below. Sorry for all the problems I caused and thank you for helping me.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
unsigned int characters[128][128][128];
int main(int argc, char* argv[]){
/*Check if input file was given*/
if(argc<2){
printf("Please enter an input file as command line argument.\n");
return 1;
}
/*Check for input file, open it*/
FILE *fp=NULL;
fp=fopen(argv[1], "r");
if(!fp){
printf("Error 404: Input file not found.\n");
return 404;
}
/*Read input text*/
int a='.'; /*pre-previous character*/
int b=' '; /*previous character*/
int c; /*current character*/
while((c=fgetc(fp))!=EOF){
if(c<127 && c>='\t'){ /*All characters from higher ASCII and system codes ignored. Still uses letters, digits and typical special characters and formatting characters.*/
characters[a][b][c]++;
a=b;
b=c;
}
}
fclose(fp);
/*Check how many sentences should be printed*/
unsigned int sentences;
printf("How many sentences do you want to be printed? ");
scanf("%d", &sentences);
/*Print text*/
unsigned int currentsentences=0, random, p1=0, p2=0, n;
a='.';
b=' ';
srand(time(0));
while(currentsentences<sentences){
n=0;
for(int i='\t'; i<127; i++){
n+=characters[a][b][i];
}
random=(rand()+p1+p2+sentences+currentsentences+clock())%n;
p1=0;
for(int i='\t'; i<127; i++){
p2=p1+characters[a][b][i]; /*Determine range for character in combination with line 58*/
if(random>=p1 && random<p2 && characters[a][b][i]!=0){ /*Check if random number is in range of character and that character occured in that combination*/
c=i;
printf("%c", c);
characters[a][b][c]++; /*Experimental, language will change over time pseudo-randomly*/
break;
}
p1+=characters[a][b][i];
}
if(c=='.' || c=='?' || c=='!')
currentsentences++;
a=b;
b=c;
}
printf("\n");
return 0;
}
The main problem is in this part of the code:
p1=0;
for(int i=0; ; i++){
p2=p1+characters[a][b][i];
if(random>p1 && random<=p2){
c=characters[a][b][i];
p1+=characters[a][b][i];
break;
}
}
Here you keep incrementing i without checking for out of bounds access. You should have something like:
if (i >= 255) { // error handling ....};
Also notice that p1 in the loop is always zero.
In this part
random=(rand()+p1+p2)%n;
p1 and p2 is uninitialized so you may end up with a negative number which obviously means that you never hit the break statement. In other words - an endless loop where you keep incrementing i (which leads to out of bounds access).
As an example I changed the code like:
for(int i=0; ; i++){
printf("random=%d p1=%d a=%c b=%c i=%d", random, p1, a, b, i);
and got output like:
...
random=-3 p1=0 a=. b= i=42484 p2=0
random=-3 p1=0 a=. b= i=42485 p2=0
random=-3 p1=0 a=. b= i=42486 p2=0
random=-3 p1=0 a=. b= i=42487 p2=0
...
Notice that random is negative so the loop can never terminate.
Warnings, Errors and some very good suggestions are pointed out in the comments under your post. nota bene.
The following comment statement seems clear enough,
/*Check how many sentences should be printed*/
but it was not clear to me what was being done in the following snippet of your code to accomplish that:
int sentences=0, multiplier=1;
for(int i=0; i<sizeof(argv[1])/8; i++){
sentences+=argv[1][i]*multiplier;
multiplier*=10;
}
So the following short snippet is a suggestion for a different approach:
// assume at minimum input of one legal filespec,
// eg: .\\filename.txt (Windows) or ./filename.txt (Linux)
int main(int argc, char *argv[])
{
FILE *fp = NULL;
int c = 0;
int sentences = 0;
if(argc<2)
{
printf("Minimum command line usage: <name>.exe [pathFileName]. Program exiting.");
getchar();
return 0;
}
fp = fopen(argv[1], "r");
if(fp)
{
c = fgetc(fp);
while(c) // will exit upon EOF (-1) Note c is int, not char
{
if( (c=='.') || (c=='?') || (c=='!') )
{
sentences++;
}
}
fclose(fp);
}
else return 0; //error, file not opened.
/* rest of your code here */
return 0;
}
The entire logic for selecting the next character is wrong:
After the loop iterating i to examine characters[a][b][i], the code sends c to output. At that point, c is either left over from some previous code or is characters[a][b][i] for some i, which means it is a count of triples that were seen during analysis—it is not a code for the character that should be printed.
The code for preparing p1 and p2 and comparing them to a random number is nonsensical. The code ought to pick a random number in [0, N), where N is the sum of characters[a][b][i] for all character codes i and then select the character code c such that c is in [p1, p2), where p1 is the sum of characters[a][b][i] for 0 ≤ i < c and p2 is p1 + characters[a][b][c].

How to sort array of strings in ascending order in C

Problem
I have made sorting program which is similiar to other found at
https://beginnersbook.com/2015/02/c-program-to-sort-set-of-strings-in-alphabetical-order/
but program which i made is not working.
I think both are same but my program giving me waste output.
Also i want to know in other program count is set to 5 for example and it should take 6 input starting from 0 but it is getting only 5,How?
My Program
#include <string.h>
#include <stdio.h>
int main() {
char str[4][10],temp[10];
int i,j;
printf("Enter strings one by one : \n");
for(i=0;i<5;i++)
scanf("%s",str[i]);
for(i=0;i<5;i++)
for(j=i+1;j<5;j++)
if(strcmp(str[i],str[j])>0){
strcpy(temp,str[i]);
strcpy(str[i],str[j]);
strcpy(str[j],temp);
}
printf("\nSorted List : ");
for(i=0;i<5;i++)
printf("\n%s",str[i]);
printf("\n\n");
return 0;
}
Use qsort().
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int pstrcmp( const void* a, const void* b )
{
return strcmp( *(const char**)a, *(const char**)b );
}
int main()
{
const char* xs[] =
{
"Korra",
"Zhu Li",
"Asami",
"Mako",
"Bolin",
"Tenzin",
"Varrick",
};
const size_t N = sizeof(xs) / sizeof(xs[0]);
puts( "(unsorted)" );
for (int n = 0; n < N; n++)
puts( xs[ n ] );
// Do the thing!
qsort( xs, N, sizeof(xs[0]), pstrcmp );
puts( "\n(sorted)" );
for (int n = 0; n < N; n++)
puts( xs[ n ] );
}
Please don’t use bubble sort. In C, you really do not have to write your own sorting algorithm outside of specialized needs.
Here is a program which will sort and print your inputted strings. Answering a little late, but just in case others have a similar question.
// This program will sort strings into either ascending or descending order
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 1000
#define EQUAL 0
#define ASCENDING 0
#define DESCENDING 1
// Function prototypes
void swap_str(char str1[], char str2[]);
void sort_strings(char str[MAX_SIZE][MAX_SIZE], int len, int order_type);
void print_2d_array(char str[MAX_SIZE][MAX_SIZE], int len);
int main(void) {
int order_type;
char str[MAX_SIZE][MAX_SIZE];
// User selecting the order type
printf("-----------[Order Type]-----------\n");
printf("Sort your strings in ascending or descending order?\n");
printf("0 = Ascending | 1 = descending\n");
scanf("%d", &order_type);
if (order_type != ASCENDING && order_type != DESCENDING) {
printf("Please enter 0 or 1\n");
exit(1);
}
// User inputting their strings
printf("---------[Enter Strings]----------\n");
printf("Enter Strings one by one.\n");
printf("Max Strings: %d | Max String Len: %d\n", MAX_SIZE, MAX_SIZE);
int i = 0;
while ((i < MAX_SIZE) && (scanf("%s", str[i]) == 1)) i++;
if (i == MAX_SIZE) printf("You reached the maximum strings allowed\n");
// Program output of the sorted strings
printf("---------[Sorted Strings]---------\n");
sort_strings(str, i, ASCENDING);
print_2d_array(str, i);
return 0;
}
// Swaps two strings (assuming memory allocation is already correct)
void swap_str(char str1[], char str2[]) {
char temp[MAX_SIZE];
strcpy(temp, str1);
strcpy(str1, str2);
strcpy(str2, temp);
}
// Will sort a 2D array in either descending or ascending order,
// depending on the flag you give it
void sort_strings(char str[MAX_SIZE][MAX_SIZE], int len, int order_type) {
int i = 0;
while (i < len) {
int j = 0;
while (j < len) {
if ((order_type == ASCENDING) &&
(strcmp(str[i], str[j]) < EQUAL)) {
swap_str(str[i], str[j]);
} else if ((order_type == DESCENDING) &&
(strcmp(str[i], str[j]) > EQUAL)) {
swap_str(str[i], str[j]);
}
j++;
}
i++;
}
}
// Will print out all the strings 2d array
void print_2d_array(char str[MAX_SIZE][MAX_SIZE], int len) {
int i = 0;
while (i < len) {
printf("%s\n", str[i]);
i++;
}
}
Example (Ascending order):
-----------[Order Type]-----------
Sort your strings in ascending or descending order?
0 = Ascending | 1 = descending
0
---------[Enter Strings]----------
Enter Strings one by one.
Max Strings: 1000 | Max String Len: 1000
Mango
Watermelon
Apple
Banana
Orange
// I pressed CTRL+D here (Linux) or CTRL+Z then enter (on Windows). Essentially triggering EOF. If you typed the MAX_SIZE it would automatically stop.
---------[Sorted Strings]---------
Apple
Banana
Mango
Orange
Watermelon
it should take 6 input starting from 0 but it is getting only 5,How?
This loop
for(i=0;i<5;i++)
scanf("%s",str[i]);
execute for i being 0, 1, 2, 3, 4 so it loops 5 times.
If you want 6 loops do
for(i=0;i<=5;i++)
^
Notice
or
for(i=0;i<6;i++)
^
Notice
Also notice this line
char str[6][10],temp[10];
^
Notice
so that you reserve memory for 6 strings
This is not an answer, but some criticism of the code you refer to:
#include<stdio.h>
#include<string.h>
int main(){
int i,j,count;
char str[25][25],temp[25];
puts("How many strings u are going to enter?: ");
scanf("%d",&count); // (1)
puts("Enter Strings one by one: ");
for(i=0;i<=count;i++) // (2)
gets(str[i]);
for(i=0;i<=count;i++)
for(j=i+1;j<=count;j++){
if(strcmp(str[i],str[j])>0){
strcpy(temp,str[i]);
strcpy(str[i],str[j]);
strcpy(str[j],temp);
}
}
printf("Order of Sorted Strings:"); // (3)
for(i=0;i<=count;i++)
puts(str[i]);
return 0;
}
And the criticism:
(1) scanf("%d",&count); reads a number into count, and returns after that. It does not consume the line break(!)
(2) this loop does not print anything, just reads. However if you put
for(i=0;i<=count;i++){
printf("%d:",i);
gets(str[i]);
}
in its place, you will suddenly see that it asks for names 0...5, just skips the 0 automatically. That is where the line break is consumed, it reads an empty string. You can also make it appear, if instead of putting 5 into the initial question, you put 5 anmoloo7.
(3) in the printout the names appear below the title Order of Sorted Strings. But there is no linebreak in that printf. The thing is that the empty string is "smaller" than any other string, so it gets to the front of the list, and that is printed there first. If you do the 'trick' of appending a name after the initial number, the output will look different, there will be 6 names, and one of them appended directly to the title.
Plus there is the thing what you probably get from your compiler too: gets is a deadly function, forget its existence and use fgets with stdin as appears in other answers.
I have this sample that I made:
#include <stdio.h>
#include <string.h>
void main()
{
char str[100],ch;
int i,j,l;
printf("\n\nSort a string array in ascending order :\n");
printf("--------------------------------------------\n");
printf("Input the string : ");
fgets(str, sizeof str, stdin);
l=strlen(str);
/* sorting process */
for(i=1;i<l;i++)
for(j=0;j<l-i;j++)
if(str[j]>str[j+1])
{
ch=str[j];
str[j] = str[j+1];
str[j+1]=ch;
}
printf("After sorting the string appears like : \n");
printf("%s\n\n",str);
}
#include <stdio.h>
#include <string.h>
#define STRING_MAX_WIDTH 255
void sort_strings(char str_arr[][STRING_MAX_WIDTH],int len){
char temp[STRING_MAX_WIDTH];
for(int i=0;i<len-1;i++){
if(strcmp(&str_arr[i][0],&str_arr[i+1][0])>0){
strcpy(temp, str_arr[i+1]);
strcpy(str_arr[i+1],str_arr[i]);
strcpy(str_arr[i],temp);
sort_strings(str_arr, len);
}
}
}
int main(){
char str_arr[][STRING_MAX_WIDTH] = {"Test", "Fine", "Verb", "Ven", "Zoo Keeper", "Annie"};
int len = sizeof(str_arr)/STRING_MAX_WIDTH;
sort_strings(str_arr, len);
for(int i=0;i<len;i++){
printf("%s\r\n", str_arr[i]);
}
}

Scan String Input for each testcase in C

the objective of my question is very simple. The first input that I get from the user is n (number of test cases). For each test case, the program will scan a string input from the user. And each of these strings I will process separately.
The question here is how can I get string inputs and process them separately in C language??? The idea is similar to the dictionary concept where we can have many words which are individual arrays inside one big array.
The program I have written so far:
#include <stdio.h>
#define max 100
int main (){
int n; // number of testcases
char str [100];
scanf ("%d\n",&n);
for (int i =0;i <n;i++){
scanf ("%s",&str [i]);
}
getchar ();
return 0;
}
Can someone suggest what should be done?
The input should be something like this:
Input 1:
3
Shoe
Horse
House
Input 2:
2
Flower
Bee
here 3 and 2 are the values of n, the number of test cases.
First of all, Don't be confused between "string" in C++ , and "Character Array" in C.
Since your question is based on C language, I will be answering according to that...
#include <stdio.h>
int main (){
int n; // number of testcases
char str [100][100] ; // many words , as individual arrays inside one big array
scanf ("%d\n",&n);
for (int i =0;i <n;i++){
scanf ("%s",str[i]); // since you are taking string , not character
}
// Now if you want to access i'th word you can do like
for(int i = 0 ; i < n; i++)
printf("%s\n" , str[i]);
getchar ();
return 0;
}
Now here instead of using a two-dimensional array, you can also use a one-dimensional array and separate two words by spaces, and store each word's starting position in some another array. (which is lot of implementation).
First of all yours is not C program, as you can't declare variable inside FOR loop in C, secondly have created a prototype using Pointer to Pointer, storing character array in matrix style datastructure, here is the code :-
#include <stdio.h>
#include <stdlib.h>
#define max 100
int main (){
int n,i; // number of testcases
char str [100];
char **strArray;
scanf ("%d",&n);
strArray = (char **) malloc(n);
for (i =0;i <n;i++){
(strArray)[i] = (char *) malloc(sizeof(char)*100);
scanf ("%s",(strArray)[i]);
}
for (i =0;i <n;i++){
printf("%s\n",(strArray)[i]);
free((strArray)[i]);
}
getchar ();
return 0;
}
#include <stdio.h>
#define MAX 100 // poorly named
int n=0; // number of testcases
char** strs=0;
void releaseMemory() // don't forget to release memory when done
{
int counter; // a better name
if (strs != 0)
{
for (counter=0; counter<n; counter++)
{
if (strs[counter] != 0)
free(strs[counter]);
}
free(strs);
}
}
int main ()
{
int counter; // a better name
scanf("%d\n",&n);
strs = (char**) calloc(n,sizeof(char*));
if (strs == 0)
{
printf("outer allocation failed!")
return -1;
}
for (counter=0; counter<n; counter++)
{
strs[counter] = (char*) malloc(MAX*sizeof(char));
if (strs[counter] == 0)
{
printf("allocate buffer %d failed!",counter)
releaseMemory();
return -1;
}
scanf("%s",&strs[counter]); // better hope the input is less than MAX!!
// N.B. - this doesn't limit input to one word, use validation to handle that
}
getchar();
// do whatever you need to with the data
releaseMemory();
return 0;
}

Resources