printing a 2d array of string in c - c

i'm trying to print a 2d array of string as practice(i'm a newbie) with no success i've tried every combination i could think of still nothing i'm sure i'm doing a silly error somewhere i just can't see it here some of the example:
using a pointer :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define lim 10
#define maxx 25
void print(char *);
int main()
{
int i = 1;
char input[lim][maxx];
char *ps = input;
printf("type the list of %d names or type quit to leave \n", lim);
while (i<lim && gets(input[i]) != NULL && strncmp(input[i], "quit", 4)!=0 ) {
i++;
}
printf("i've counted %d names\n", i);
print("\n");
print(ps);
return 0;
}
void print(char *a)
{
int i=0;
printf("the list of names include : \n");
while(*(a) != '\0') {
printf("%s\n", *(a+i));
i++;
}
}
here's the output:
type a list of %d names or type quit to leave :
bla
bli
blo
quit
i've counted 4 names
the list of names include :
segmentation fault (core duped)
another version of the print function is like this :
void print(char aray[lim][maxx])
{
int i,j;
printf("the list of names include : \n");
for(i = 0; i < lim; i++) {
for(j = 0; j < maxx; j++){
puts(aray[i][j]);
//printf("%s\n", aray[i][j]);
}
}
}
i get the same output, can anyone help me debug this ? and thx in advance

In short, it looks like you need to brush up on your pointers. With your original print function:
void print(char *a)
{
int i=0;
printf("the list of names include : \n");
while(*(a) != '\0') {
printf("%s\n", *(a+i));
i++;
}
}
You are printing the value at a + i every iteration. This might sound like what you want, but what you actually pass to print is a pointer to an array of arrays of char (your compiler should be throwing a warning about incompatible pointer types). That is, the "proper" type of ps is (char *)[]. So in the print function you are only advancing the memory address by sizeof(char) with each iteration, whereas what you actually want is to increment it by sizeof(char) * maxx (the size of your array entries). To implement this change, do the following:
change declaration of print
void print(char (*)[maxx]);
change to proper pointer type
char (*ps)[maxx] = input;
And finally, change print function to something like:
void print(char (*a)[maxx]){
printf("the list of names include : \n");
int i;
for (i = 0; i < lim; i++){
printf("%s\n",*a);
a++;
}
}
You need not use the (a+i) syntax, as just advancing a by one each iteration accomplishes the same thing, and is possibly faster for large i. And of course, as others have mentioned, double check your new line printing, I believe you want printf('\n').

You are adding i as 1 which will not help in case of your two dimensional array as the next element will be at maxx location,so you can do something like this
//here lim and max are defined in your program
void print(char *a){
int i=0;
printf("the list of names include : \n");
while(i<(lim*maxx)){
printf("%s\n",a );
i += maxx;
a = a + maxx;
}
}
and the second variant should be
void print(char aray[lim][maxx])
{
int i,j;
printf("the list of names include : \n");
for(i = 0; i < lim; i++) {
cout<<aray[i]<<"\n";
}
}

You start on index 1 in your 2d array, you should start with index 0
int i=1;
Your print function takes an array of characters and then does a printf string of each character which makes no sense
void print(char *a)
{
int i=0;
printf("the list of names include : \n");
while(*(a)!='\0')
{
printf("%s\n",*(a+i));
i++;
}
}
instead make it look like this
void print(char *a[], int strings)
{
int i = 0;
for (; i < strings; ++i)
{
puts( a[i] );
}
}
and call it with the number of strings you read
print(ps,i);
You would also be better off using fgets() instead of gets(), especially since your strings are max 25 chars so its easy to give a longer string. fgets() lets you specify the max size of the string fgets(input[i],maxx,stdin)
Your other function
void print(char aray[lim][maxx])
{
int i,j;
printf("the list of names include : \n");
for(i = 0; i < lim; i++) {
for(j = 0; j < maxx; j++){
puts(aray[i][j]);
//printf("%s\n", aray[i][j]);
}
}
}
does a similar wrong assumption about the level of indirection
arra[i][j] is one character but puts takes a string argument, so puts( arra[i][j] ); is not correct, you could try fputc( arra[i][j], stdout ) instead since fputc takes one character

fix to
void print(char (*)[maxx]);
int main()
{
int i = 0;//int i = 1;
char input[lim][maxx] = { {'\0'}};
char (*ps)[maxx] = input;
printf("type the list of %d names or type quit to leave \n", lim);
while (i<lim && gets(input[i]) != NULL && strncmp(input[i], "quit", 4)!=0 ) {
i++;
}
printf("i've counted %d names\n", i);
printf("\n");//print("\n");
print(ps);
return 0;
}
void print(char (*a)[maxx])
{
int i=0;
printf("the list of names include : \n");
while(i<lim && a[i][0] != '\0') {
printf("%s\n", a[i]);
i++;
}
}

Related

Error: value computed is not used [-Werror=unused-value]

Ive written this code to try and read if there are any duplicate letters in a word, but I keep coming across this error:
Error: value computed is not used [-Werror=unused-value]
The line in question is:
arr[(int)(str[i])++];
The whole code is:
#include<stdio.h>
#include<string.h>
int main()
{
char str[30];
printf("Enter your String:");
scanf("%[^\n]",str);
int i;
int arr[256]={0};
for(i=0;i<strlen(str);i++)
{
if(str[i]==' '){
continue;
arr[(int)(str[i])++];
}
}
printf("Repeated character in a string are:\n");
for(i=0;i<256;i++)
{
if(arr[i]>1)
{
printf("%c occurs %d times\n",(char)(i),arr[i]);
}}
return 0;
}
Here is the error message from the console:
https://i.stack.imgur.com/GpMOW.png
Any help is appreciated :)
I've made some changes to the code, shown in comment.
#include <stdio.h>
#include <string.h>
int main()
{
char str[30];
printf("Enter your String:");
scanf("%29[^\n]", str); // limit the input length
int i;
int arr[256] = { 0 };
for(i = 0; i < strlen(str); i++)
{
if(str[i] == ' '){
continue;
}
// this line was repositioned so that it can execute
// char can be signed, so don't index by a negative value
// the post-increment should apply to the `arr[]` array element
arr[ (unsigned char)str[i] ]++;
}
printf("Repeated character in a string are:\n");
for(i = 0; i < 256; i++)
{
if(arr[i] > 0) // inform *any* usage
{
// (char)i gets promoted to int anyway
printf("%c occurs %d times\n", i, arr[i]);
}
}
return 0;
}
Session:
Enter your String:one two
Repeated character in a string are:
e occurs 1 times
n occurs 1 times
o occurs 2 times
t occurs 1 times
w occurs 1 times

C - numbers not entering in the "if condition", dont know why

So, basically, I was instructed to make a function that asks the user for a size, and then creates an array with elements chosen by the user...
for example: size:4 , input:10 20 30 40, created array = {10,20,30,40}.
Then next step the user is to apply some function for this created array. Example:
For example, if the user chooses letter 'A' the function "add1" will be applied and all elements of the array will be increased in one unit, so with an input example of {10,20,30,40}, the output will be {11,21,31,41}.
My code is not working, why? Someone can help me? I've used the debugger and the function is not entering in the "if condition".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* add1(int* array, int size)
{
int *novo;
novo = malloc(size*sizeof(int));
for (int i = 0; i < size; i++){
*(novo + (i)) = *(array + i)+1;
}
return novo;
};
int* add2(int* array, int size)
{
int *novo;
novo = malloc(size*sizeof(int));
for (int i = 0; i < size; i++){
*(novo + (i)) = *(array + i)+2;
}
return novo;
};
void print1(int* array, int size)
{
for (int i = 0; i < size; i++)
{
printf("%i\n", *(array+i));
}
};
int main(void)
{ int i, elemento, size;
char *new;
printf("Insert Size:\n");
scanf("%i", &size);
int newArray[size];
printf("Insert Elements:\n");
for (i = 0; i < size; i++)
{
scanf("%i", &elemento);
newArray[i] = elemento;
}
printf("Select option:\n");
scanf(" %c", &new);
if (new == 'A') {
int* result;
result = add1(&newArray, size);
print1(result, size);
} else if (new == 'B') {
int* result;
result = add2(&newArray, size);
print1(result, size);
} else if (new == 'C') {
} else if (new == 'D') {
}
}
Change:
char *new;
to
char new;
as
scanf(" %c", &new);
is expecting a character and as the code stands new is an undefined character pointer. So passing a pointer to a undefined pointer is not good.
PLEASE SWITCH ON YOUR COMPILER WARNINGS AND THIS WOULD BE PICKED UP!
new is not a good variable name. As it leads to confusion with C++ keyword
Check the return values for scanf- see the manual page for that
Perhaps using switch instead of if new == 'A' .....

Printing vertical histogram

I am trying to print a vertical histogram that counts the frequency of each digit input by the user.
I store the frequency first as follows:
int a[10]; //array
int c; //store input from getchar
int i; //loop variable
for(i=0;i<10;i++)
{
a[i]=0; //initialize to 0
}
while((c=getchar())!=EOF) //read character
{
++a[c-'0'];
}
Next, I try to draw a vertical histogram.
for(i=10;i>0;i--) //asssumed max limit of frequency is 10
{
int j; //iterate through the array
for(j=0;j<10;j++)
{
if(a[j]==i) //if frequency of any element in array matches i
{
printf("* \t");
--a[j]; //decrement array element frequency value
}
else
printf(" \t"); //no action
}
printf("\n"); //next line
}
The problem is when I try to print the histogram, I get a blank screen. I have tested it with horizontal histogram and it works.
Taking exactly your code, formatting it for readability, and adding a check to ensure that only digits are used to avoid breaking things further, it worked. The check was not necessary for functionality, but it's a good idea to avoid writing out of the bounds of the array.
#include <stdio.h>
#include <ctype.h>
int main() {
int a[10]; //array
int c; //store input from getchar
int i; //loop variable
for(i=0;i<10;i++)
{
a[i]=0; //initialize to 0
}
while((c=getchar())!=EOF) //read character
{
if (isdigit(c))
++a[c - '0'];
}
for(i=10;i>0;i--) //asssumed max limit of frequency is 10
{
int j; //iterate through the array
for(j=0;j<10;j++)
{
if(a[j]==i) //if frequency of any element in array matches i
{
printf("* \t");
--a[j]; //decrement array element frequency value
}
else
printf(" \t"); //no action
}
printf("\n"); //next line
}
}
Result:
$ ./a
0123456789666338592
*
* *
* * * * * *
* * * * * * * * * *
For reference, this was compiled for Cygwin.
I've also modified your source code in a few ways to correspond with some of the practices that I follow:
#include <stdio.h>
#include <ctype.h>
int main()
{
int a[10] = {0}; // While use a for to initialize to 0 when you can do it easily?
int i;
char c;
while((c = getchar()) != EOF)
{
if (isdigit(c)) // Never trust the user
a[c - '0']++; // Changed for readability, make it clear that we are incrementing the value, not the pointer.
}
for(i = 10; i > 0; --i)
{
int j;
for(j = 0; j < 10; ++j)
{
// Made flow a little clearer
if(a[j] >= i)
putchar('*');
else
putchar(' ');
putchar('\t');
}
putchar('\n');
}
}
What you do is of course up to you, I just personally find this more consistent.

Segmentation Fault: 11 C sometimes

I'm trying to run a program in C on my mac that asks the user to input a set of names. The program then sorts and capitalizes all the names and prints them capitalized and sorted. It then allows the user to search for a name. However, most of the time (but not every time) I try to run the code it returns a segmentation fault: 11 error. My guess is that the problem has something to do with fgets or my array but I don't really know.
Here's my code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define SIZE 50
#define LENGTH 50
#define TRUE 1
#define FALSE 0
void printList(char names[SIZE][LENGTH], int length);
void toUpperCase(char names[SIZE][LENGTH], int length);
void sort(char names[SIZE][LENGTH], int length);
void startSearch(char names[SIZE][LENGTH], int length);
int binSearch(char names[SIZE][LENGTH], int l, int r, char x[LENGTH]);
int main(void){
char names[SIZE][LENGTH]; //stores the list of names
printf("Enter student names (q to stop)...\n");
int i = 0;
do {
printf("Student name #%d: ", i);
fgets(names[i], LENGTH, stdin); //fill the list of names
int len = strlen(names[i])-1; //fgets includes \n character
if(names[i][len] == '\n') //if the last character is \n
names[i][len] = '\0'; //change it to \0
if(strcmp(names[i], "") == 0)
printf("Invalid input: Type a name\n");
else
i++;
}
while(strcmp(names[i-1],"q")!=0 && i<SIZE); //Stop collecting names after input "q"
//or if the names array is full
int length = i-1; //# of names in the names array
sort(names, length);
toUpperCase(names, length);
printList(names, length);
startSearch(names, length);
printf("Done!\n");
return 0;
}
//Converts all the names in the names array to upper case
void toUpperCase(char names[SIZE][LENGTH], int length){
for(int i = 0; i < length; i++){
for(int j = 0; names[i][j]!='\n'; j++){
if(islower(names[i][j]))
names[i][j] = toupper(names[i][j]);
}
}
}
//sorts the names in the names array (bubble sort)
void sort(char names[SIZE][LENGTH], int length){
int i, j;
char temp[LENGTH];
for (i = 0; i < length-1; i++)
for (j = 0; j < length-i-1; j++)
if (strcmp(names[j],names[j+1])>0){
strcpy(temp, names[j]);
strcpy(names[j], names[j+1]);
strcpy(names[j+1], temp);
}
}
//prints the names in the names array
void printList(char names[SIZE][LENGTH], int length){
printf("Student list: [\n");
for(int i = 0; i < length; i++)
if(i == length-1)
printf("\t%s\n", names[i]);
else
printf("\t%s,\n", names[i]);
printf("]\n");
}
//The first method for searching the list
void startSearch(char names[SIZE][LENGTH], int length){
char search[LENGTH];
while(strcmp(search, "q")!=0){
printf("Enter a name to search (q to exit): ");
fgets(search, LENGTH, stdin); //gets the name to search
int len = strlen(search)-1;
if(search[len] == '\n')
search[len] = '\0';
if(strcmp(search, "q") == 0) //if entered value is q
break; //break out of the loop
//Since the list is all upper case change the search value to upper case
for(int j = 0; search[j]!='\n'; j++){
if(islower(search[j]))
search[j] = toupper(search[j]);
}
printf("Searching for %s ...\n", search);
// if binSearch returns true then the item is in the list
if(binSearch(names, 0, length-1, search) == TRUE)
printf("%s is in the list!\n", search); /
else
printf("%s is NOT in the list!\n", search);
}
}
//binary search for the names array
int binSearch(char names[SIZE][LENGTH], int l, int r, char x[LENGTH]){
while (l <= r)
{
int m = l + (r-l)/2;
if(strcmp(names[m], x) == 0)
return TRUE;
if(strcmp(names[m], x) < 0)
l = m + 1;
else
r = m - 1;
}
return FALSE;
}
I assume you're using fixed arrays of SIZE and LENGTH for learning purposes. For actual string-related work, you'd do well to heed kpra's advice and using the more complex, but more powerful, pointers (allocating them and deallocating at need).
In your reading loop you kill all the "\n"'s replacing them with zeroes.
Yet in your toUppercase() code you look for a "\n" instead of a 0x0. This risks blowing the buffer:
//Converts all the names in the names array to upper case
void toUpperCase(char names[SIZE][LENGTH], int length){
for(int i = 0; i < length; i++){
for(int j = 0; names[i][j]!='\n'; j++){
// what happens here if \n is not found and j exceeds SIZE?
if(islower(names[i][j]))
names[i][j] = toupper(names[i][j]);
}
}
}
You could replace \n with 0x0, but I think a safer loop would be:
for(int j = 0; j < SIZE; j++) {
if (yourstring[j] == 0) {
break;
}
This way you're sure never to overshoot SIZE, and the cycle is ended anyway if the end of string is found. Notice that this '\n' comparison is used also in the search loop.

making a word search puzzle?

I've made a program that allows you to choose the size of the grid and it allows you to enter up to 20 words. Now I have to insert the entered words horizontally into the original array using a function. The function must return a value for success and a value for failure to enter the word into the puzzle board. I need help getting started with what the actual function should look like along with the function prototype. Pseudocode would be helpful. I'm a fairly new programmer so any help is great. Thank you
#include<stdio.h>
#include<string.h>
void printmatrix(char matrix[][20],int);
void inserthor(char matrix[][20],int);
int main(void)
{
//declare variables
char matrix[20][20];
char words[20][100];
int x;
int a,b;
int i=0;
int n=0;
for (a=0;a<20;a++)
{
for (b=0;b<20;b++)
{
matrix[a][b] = '+';
}
}
while (x<10 || x>20)
{
printf("How large would you like the puzzle to be (between 10 and 20):\n");
scanf("%d",&x);
}
printmatrix(matrix,x);
//part 3
printf("Enter up to 20 words to hide in the puzzle.\n");
printf("Enter the word 'done' after your last word if entering less than 20 words.\n");
for (i = 0; i < 20; i++)
{
printf("Enter word %2d:\n", i+1);
if (scanf("%99s", words[i]) != 1 || strcmp(words[i], "done") == 0)
break;
}
n = i;
printf("%d words entered\n", n);
for (i = 0; i < n; i++)
printf("Word %2d = [%s]\n", i+1, words[i]);
return 0;
}
void printmatrix(char matrix[][20],int x)
{
int i,j;
printf("Empty Puzzle:\n");
for (i=0;i<x;i++)
{
for (j=0;j<x;j++)
{
printf(" %c ", matrix[i][j]);
}
printf("\n");
}
}
Your function prototype
void inserthor(char matrix[][20],int);
lacks the parameter with the word to be entered and the value to be returned. You could use
char *inserthor(char matrix[][20], int order, char *word)
{
int i, j, l = strlen(word);
for (i = 0; i < order; ++i)
for (j = 0; j <= order-l; ++j)
if (matrix[i][j] == '+') return memcpy(&matrix[i][j], word, l);
return NULL;
}
which returns the address of the inserted word for success and NULL for failure.

Resources