C programming problem pointers and arrays 2d - c

Q2: Implelment the follwoing function ArrPrintMatrix(char *(p)[7]) which prints the content of the matrix[m][7] ={"SHAHBAZ","AYAZ"} in to 3x3 Matrix
Sample Output
S H A
H B A
Z A Y ..
My question is : here is code only problem i am getting is a space after one name is completed..how to remove that space . I have this question in my assignments , that have to be submitted on sunday (11-11-18)..
My code is:
#include<stdio.h>
int main()
{
void ArrPrintMatrix(char *p);//function declaration
char matrix[2][8] ={"SHAHBAZ","AYAZ"};//2d array initiliation
ArrPrintMatrix(&matrix[0][0]);//calling function with base address
}
void ArrPrintMatrix(char *p)
{
int i;
for(i=0;i<16;i++)
{
if(i>=9)//since 3 by 3 matrix is required
break;
if(i==3||i==6||i==9)//changing line since 3 by 3 matrix is needed
printf("\n");
printf("%c ",*(p+i));//prininting chracters
}
}

You should use char (*p)[8] not char* p
The following code could wrok:
#include<stdio.h>
int main()
{
void ArrPrintMatrix(char (*p)[8]);//function declaration
char matrix[2][8] ={"SHAHBAZ","AYAZ"};//2d array initiliation
ArrPrintMatrix(matrix);//calling function with base address
}
void ArrPrintMatrix(char (*p)[8])
{
// i will point to one of the strings in the set of strings
// j will point into the string we are inspecting
// k will count how many characters we have printed
int i = 0, j = 0, k = 0;
// we only need to print the first 9 printable characters we find
while (k != 9)
{
// if we have reached the end of an input string (the null-terminator),
// then move on to the next element in the array, and reset
// the string pointer to the beginning of the new string
if (p[i][j] == '\0') {
++i;
j = 0;
}
// print the character we are now pointing at,
// and increment the string pointer
printf("%c ", p[i][j++]);
// keep count of how many characters we have printed
++k;
// if k is divisible by 3, start a new row
if(k%3 == 0)
printf("\n");
}
}

As a follow-on to my other answer, if you do use my logic to skip over the '\0' that terminates the strings, you will need to use a different variable to keep track of how many characters you've actually printed, and just let i keep track of where you are in the input string(s). Like so:
#include<stdio.h>
int main()
{
void ArrPrintMatrix(char *p);//function declaration
char matrix[2][8] ={"SHAHBAZ","AYAZ"};//2d array initiliation
ArrPrintMatrix(&matrix[0][0]);//calling function with base address
}
void ArrPrintMatrix(char *p)
{
int i, j;
for(i=0, j=0;i<16;i++)
{
if(j>=9)//since 3 by 3 matrix is required
break;
if(j==3||j==6||j==9)//changing line since 3 by 3 matrix is needed
printf("\n");
if (*(p+i)==0) continue; //don't try to print the trailing '\0'
printf("%c ",*(p+i));//prininting chracters
j++; //increment counter of characters actually printed
}
}
Output:
S H A
H B A
Z A Y
Note the use of the j variable, and how it is incremented with j++ only after actually printing a character.

What you are missing is that there is a trailing '\0' at the end of SHAHBAZ, which you are also "printing", but because '\0' does not have a character representation, you are seeing what looks like an 'extra' space.
Here is the smallest change I can think of to address this exact problem; add:
if (*(p+i)==0) continue; //don't try to print the trailing '\0'
just above your existing line:
printf("%c ",*(p+i));//prininting chracters
Output:
S H A
H B A
Z A
There are other things I would do differently than how you are doing them, but this addresses your exact question, using your coding style.

Related

How to get the length of this array without strlen(), sizeof(arr) / sizeof(arr[0]); does not work, C language

This program, tokenizes a user input string, removes extra spaces and saves each word into a 2D array and then print the tokens
EXAMPLE:
input: " Hello world string house and car"
output and EXPECTED output:
token[0]: Hello
token[1]: world
token[2]: string
token[3]: house
token[4]: and
token[5]: car
THE PROBLEM:
the problem is that I achieved this by using strlen() function when printing the tokens(code located at the very bottom), I am not supposed to use any other library than stdio.h and stdlib.h, since strlen() function is defined in string.h i tried to use sizeof(arr) / sizeof(arr[0]); but it does not work as I want, the result using sizeof is :
token[0]: Hello
token[1]: world
token[2]: string
token[3]: house
token[4]: and
token[5]: car
�oken[6]: ��
token[7]: �
token[8]: ����
token[9]: �
token[10]:
I WOULD LIKE TO HAVE THE EXPECTED OUTPUT WITHOUT USING STRLEN()
#include<stdio.h>
#include <stdlib.h>
#define TRUE 1
char tokenize(char *str, char array[10][20])
{
int n = 0, i, j = 0;
for(i = 0; TRUE; i++)//infinite loop until is the end of the string '\0'
{
if(str[i] != ' '){
//position 1, char 1
array[n][j++] = str[i];// if, it is not space, we save the character
}
else{
array[n][j++] = '\0';//end of the first word
n++;// position for next new word
j=0;// start writting char at position 0
}
if(str[i] == '\0')
break;
}
return 0;
}
//removes extra spaces
char* find_word_start(char* str){
/*also removes all extra spaces*/
char *result = (char*) malloc(sizeof(char) *1000);
int c = 0, d = 0;
// no space at beginning
while(str[c] ==' ') {
c++;
}
while(str[c] != '\0'){ // till end of sentence
result[d++] = str[c++]; //take non-space characters
if(str[c]==' ') { // take one space between words
result[d++] = str[c++];
}
while(str[c]==' ') { //
c++;
}
}
result[d-1] = '\0';
//print or return char?
return result;
free(result);
}
int main()
{
char str[]=" Hello world string dudes and dudas ";
//words, and chars in each word
char arr[10][20];
//call the method to tokenize the string
tokenize(find_word_start(str),arr);
int row = sizeof(arr) / sizeof(arr[0]);
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
for(int i = 0;i <= strlen(arr);i++)
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
printf("token[%d]: %s\n", i, arr[i]);
return 0;
}
Your code using strlen() may appear the work in this instance but it is not correct.
strlen(arr) makes no semantic sense because arr is not a string. It happens in this case to return 5 because arr has the same address as arr[0], then you kludged it to work for the 6 word output by using the test i <= strlen(arr) in the for loop. The two values strlen(arr) and the number of strings stored in arr are not related.
The expression sizeof(arr) / sizeof(arr[0]) determines the run-time constant number arrays within the array of arrays arr (i.e. 10), not the number of valid strings assigned. It is your code's responsibility to keep track of that either with a sentinel value such as an empty string, or by maintaining a count of strings assigned.
I suggest you change tokenize to return the number of strings (currently it is inexplicably defined to return a char, but in fact only ever rather uselessly returns zero):
int tokenize( char* str, char array[][20] )
{
...
return n ;
}
Then:
int rows = tokenize( find_word_start(str), arr ) ;
for( int i = 0; i < rows; i++ )
{
printf( "token[%d]: %s\n", i, arr[i] ) ;
}

How to convert logic to pointer logic

How to covert logic to pointer logic, so below i have it the way I understand to code, but I need this to be using pointer like it says in the TODO, please advise, TY :)
This is what is said in the TODO that is not helping me understand, (Hint: to avoid doing double pointer arithmatic, save a char* pointer
// to the active chunk[?] in the outer loop but before the inner loop.
// Then the inner loop is only concerned with a single array of
// characters rather than an array of strings.)
Loop over each string in the array of
// message chunks (strings) and print it. Do not print the first
// character in each string since it is only used to store the order of
// the chunks. (Hint: use pointer arithmetic to skip a character.)
////////////////////////////////////////////////////////////////////////////////
//INCLUDES
#include <stdio.h>
#include <string.h>
//macros: constants
#define CHUNK_LENGTH (20+1) //each chunk has twenty characters, we add 1 so
//there is space for the null terminator.
#define NUMBER_OF_CHUNKS 4 //the message is spread across 4 chunks.
#define DECRYPTION_SHIFT 5 //this is the ASCII table shift used for decryption.
//forward declarations
void sort_chunks();
void decrypt_chunks();
void display_chunks();
char chunks[NUMBER_OF_CHUNKS][CHUNK_LENGTH];
int main() {
//copy message into memory.
strcpy(chunks[0], "2i1%fsi%fs%jstwrtzx%");
strcpy(chunks[1], "1'H%nx%vznwp~1%kqf|j");
strcpy(chunks[2], "4R3%Wnyhmnj%%%%%%%%%");
strcpy(chunks[3], "3xzhhjxx3'%2%Ijssnx%");
//the format of a chunk is a single number indicating its order in overall
//message followed by twenty encrypted characters.
//reorder chunks in message by sorting them based on the first digital
//they contain. looking above, one can see they are currently in the order
//2, 1, 4, 3 but should be ordered 1, 2, 3, 4.
sort_chunks();
//shift the characters in the message to produce the original characters.
decrypt_chunks();
//display the decrypted message.
display_chunks();
return 0;
}
//given two strings, swaps their contents in memory.
void swap_strings(char* x, char* y) {
//create a temporary holding place for the data so we don't lose it.
char temp[CHUNK_LENGTH];
strcpy(temp, x);
strcpy(x, y);
strcpy(y, temp);
}
//sorts the strings the global chunks variable by the first character they contain.
void sort_chunks() {
//TODO: Implement sort_chunks(). Using your favorite sorting algorithm (we
// suggest selection sort), sort the array containing the message chunks.
// Sort based on the first character in the chunk - it will always be a
// number. We provide a swap_strings function that you may use. Example
// usage: swap_strings(chunks[0], chunks[1]) will swap the contents of
// the first and second string.
int i, j;
int lowest;
for (i = 0; i < NUM_OF_CHUNKS - 1; i++)
{
lowest = i;
for (j = i + 1; j < NUM_OF_CHUNKS; j++)
{
if (chunks[j][0] < chunks[lowest][0])
lowest = j;
}
swap_strings(chunks[i], chunks[lowest]);
}
}
//for each string in the global chunks variable, shifts the characters in it by
//DECRYPTION_SHIFT.
void decrypt_chunks() {
//TODO: Implement decrypt_chunks(). Loop over each string in the array
// and shift the characters in it by subtracting DECRYPTION_SHIFT value
// from them. Use pointer arithmetic to access individual characters but
// array access to the strings. Remember that C-style strings have a null
// terminator at the end. Do not apply the shift to the terminator.
// (Hint: to avoid doing double pointer arithmetic, save a char* pointer
// to the active chunk[?] in the outer loop but before the inner loop.
// Then the inner loop is only concerned with a single array of
// characters rather than an array of strings.)
int row, col;
for (row = 0; row < NUM_OF_CHUNKS; row++)
{
for (col = 0; col < CHUNK_LENGTH - 1; col++)
{
if (chunks[row][col] != '\0')
chunks[row][col] -= DECRYPTION_SHIFT;
}
}
}
//displays the strings in the global chunks variable
void display_chunks() {
//TODO: Implement display_chunks(). Loop over each string in the array of
// message chunks (strings) and print it. Do not print the first
// character in each string since it is only used to store the order of
// the chunks. (Hint: use pointer arithmetic to skip a character.)
int row, col;
for (row = 0; row < NUM_OF_CHUNKS; row++)
{
for (col = 1; col < CHUNK_LENGTH - 1; col++)
{
if (chunks[row][col] == '\0')
{
printf("\n");
return;
}
printf("%c", chunks[row][col]);
}
}
printf("\n");
}
Let's make this instructive. Let's use a simple preprocessor define WPOINTERS to allow your code to be compiled to use pointer or use the two loops in your original code:
//displays the strings in the global chunks variable
void display_chunks() {
//TODO: Implement display_chunks(). Loop over each string in the array of
// message chunks (strings) and print it. Do not print the first
// character in each string since it is only used to store the order of
// the chunks. (Hint: use pointer arithmetic to skip a character.)
int row;
for (row = 0; row < NUMBER_OF_CHUNKS; row++)
{
#ifdef WPOINTERS
char *p = chunks[row];
printf ("%s", p + 1);
#else
int col;
for (col = 1; col < CHUNK_LENGTH - 1; col++)
{
if (chunks[row][col] == '\0')
{
putchar ('\n');
return;
}
putchar (chunks[row][col]);
}
#endif
}
putchar ('\n');
}
If you specify -DWPOINTERS on the command line during compile, the following code is executed:
#ifdef WPOINTERS
char *p = chunks[row];
printf ("%s", p + 1);
otherwise, your original code is executed:
#else
int col;
for (col = 1; col < CHUNK_LENGTH - 1; col++)
{
if (chunks[row][col] == '\0')
{
putchar ('\n');
return;
}
putchar (chunks[row][col]);
}
In both cases you obtain:
$ ./bin/prnwptrsnew
"C is quirky, flawed, and an enormous success." - Dennis M. Ritchie
Example compile strings would be:
$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -DWPOINTERS -o bin/prnwptrsnew prnwptrs.c
or for your original code, just omit -DWPOINTERS:
$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -o bin/prnwptrsnew prnwptrs.c
If you are using cl.exe, the with/without -DWPOINTERS works the same.

Getting a value from a char array

I have written a function below to take a char array and manipulate its values (namely, convert the char to an int if it is a number). However, I have a question with how the char array is managed. When I look at input[i], it is the correct value (the value that was placed in the array. However, &input[i] gives a capital letter, and I don't know why it does that. For example, if I enter "11" and trace the variables, I might get the following result:
input[0] is 1
&input[0] is D
input[1] is 1
&input[1] is E
On to my code, if I try to use input[i], I get the error of "passing argument makes pointer from integer without cast". If I use &input[i], the code compiles but I get the wrong result. What's going on with this, and how do I access the value I'm trying to get?
Below is my code:
void myFunction(char *input) {
Queue* numberQueue = queue_new();
Queue* opQueue = queue_new();
int i = 0;
int j;
for (j = 0; j < strlen(input); j++) {
printf("input[%d] is %c\n", i, input[i]);
printf("&input[%d] is %c\n", i, &input[i]);
int number = (int)input[i];
/* queue_push_tail(queue, data) */
queue_push_tail(numQueue, number); /* ERROR */
/* rest of code omitted */
i++;
}
}
If I understand that you want to push each digit in the input character string into queue_push_tail, as an integer value then you want your loop to do something like this:
for (j = 0; j < strlen(input); j++) {
if ( input[j] >= '0' && input[j] <= '9')
{
number = input[j] - '0';
/* queue_push_tail(queue, data) */
queue_push_tail(numQueue, number); /* ERROR - FIXED*/
/* rest of code omitted */
}
}
Recall, ASCII characters are themselves unsigned integers. You simply need to adjust the value for each character by subtracting the value of ASCII '0'. If you need to collect all numbers from the string into a single number (e.g. ac7f9gh3 => 793) then simply store the values unadjusted in a temp string, and then call atoi (temp).

Find character frequency in a string

Im trying to find character frequency in a string,i wrote the following code,but it does'nt show any output.All im trying is to fill the character array with respective counts.
When i tried to debug,it some how gives output,but prints some garbage value.
#include<stdio.h>
/* Program for printing character frequency in string */
charcount(char *,int *);
int main()
{
int n,i=0;
printf("Enter n :");
scanf("%d",&n);
char var[n];
int count[100]; // array for storing character frequency
printf("Enter string :");
fflush(stdin);
scanf("%s",var);
charcount(var,count); // calling frequeny function
for(i=0;i<strlen(count);i++)
{
printf("%d\n",count[i]);
}
getch();
return 0;
}
charcount(char *p,int *q)
{
for(;*p;p++)
{
q[*p]++;
}
}
You have few problems in your code:
count array is not initialized.
You are applying strlen() on an integer array.
count array should be 256 (count[256]) to cover all possible ascii chars. For example, if your input is abcd you'll go out of bound of array as d is 100.
You are printing the wrong count:
printf("%d\n",count[i]); should be printf("%d\n",count[var[i]]);
Declare proper prototype for charcount().
After fixing these:
#include<stdio.h>
/* Program for printing character frequency in string */
void charcount(char *,int *);
int main()
{
int n,i=0;
printf("Enter n :");
scanf("%d",&n);
char var[n];
int count[256]={0}; // array for storing character frequency
printf("Enter string :");
scanf("%s",var);
charcount(var,count); // calling frequeny function
for(i=0;i<strlen(var);i++)
{
printf("%d\n",count[var[i]]);
}
return 0;
}
void charcount(char *p,int *q)
{
for(;*p;p++)
{
q[*p]++;
}
}
Make sure to compile in C99 or C11 (e.g. gcc -std=c99 file.c) mode as VLAs are not supported in earlier standards of C.
You need to initialize your count array. Otherwise it will have garbage values in it by default. You can initialize the whole array to 0 like so:
int count[100] = {0};
Your count array may not be large enough to hold all printable values (even assuming ASCII), and it should be 0 initialized. Your for loop should be checking against the length of var, not count, since you cannot sensibly treat the count integer array as a string.
int count[1<<CHAR_BIT] = {};
/*...*/
for(i=0;i<strlen(var);i++)
{
printf("%d\n",count[var[i]]);
}
Well, it really depends on what you want to output. If you intend to output all of count, then:
for(i=0;i<sizeof(count)/sizeof(count[0]);i++)
{
printf("%d\n",count[i]);
}
int count is nothing but a hashmap
Your code will not work for this string "abcd"
count['a'] = val // Works fine ASCII value of a is 97
count['b'] = val // Works fine ASCII value of a is 98
count['c'] = val // Works fine ASCII value of a is 99
count['d'] = val ; // Undefined Behaviour ASCII value of d is 100
The size should be equal to ASCII set length
int count[128] = {};
JAVA program to print "*" as much times as the occurrence of a character in String.
Or char_in_String : frequency of char_in_String
Instead of * you can print frequency count
public class CharFreq
{
public static void main(String[] args)
{
String s = "be yourself "; System.out.println(s);
int r=0;
char[] str = s.toCharArray();
for (int i = 0; i < str.length; i++)
{
int cnt = 0;
if (str[i] != ' ')
{
for (int j = 0; j < str.length; j++)
{
if (str[i] == str[j])
{
cnt++; r=j;
}
}
if(i==r)
{
System.out.print(str[i] + ":");
for (int k = 1; k <=cnt; k++)
System.out.print("*");
System.out.println();
}
}
}
}
}
Output:
be yourself
b:*
y:*
o:*
u:*
r:*
s:*
e:**
l:*
f:*
Your count[100] is not large enough. Assume you only enter "A - Z" or "a - z" it's still not large enough because 'z' is 122, then your charcount will increase count[122].
You should consider change int count[100] to int count[128] = { 0 }

Array manipulation in C

I am like 3 weeks new at writing c code, so I am a newbie just trying some examples from a Harvard course video hosted online. I am trying to write some code that will encrypt a file based on the keyword.
The point is each letter of the alphabet will be assigned a numerical value from 0 to 25, so 'A' and 'a' will be 0, and likewise 'z' and 'Z' will be 25. If the keyword is 'abc' for example, I need to be able to convert it to its numerical form which is '012'. The approach I am trying to take (having learned nothing yet about many c functions) is to assign the alphabet list in an array. I think in the lecture he hinted at a multidimensional array but not sure how to implement that. The problem is, if the alphabet is stored as an array then the letters will be the actual values of the array and I'd need to know how to search an array based on the value, which I don't know how to do (so far I've just been returning values based on the index). I'd like some pseudo code help so I can figure this out. Thanks
In C, a char is an 8-bit integer, so, assuming your letters are in order, you can actually use the char value to get the index by using the first letter (a) as an offset:
char offset = 'a';
char value = 'b';
int index = value - offset; /* index = 1 */
This is hard to answer, not knowing what you've learned so far, but here's a hint to what I would do: the chars representing letters are bytes representing their ASCII values, and occur sequentially, from a to z and A to Z though they don't start at zero. You can cast them to ints and get the ascii values out.
Here's the pseudo code for how I'd write it:
Cast the character to a number
IF it's between the ascii values of A and Z, subtract it from A
ELSE Subtract it from the ASCII value of a or A
Output the result.
For what it's worth, I don't see an obvious solution to the problem that involves multidimensional arrays.
char '0' is the value 48
char 'A' is the value 65
char 'a' is the value 97
You said you want to learn how to search in the array:
char foo[26]; //your character array
...
...
//here is initialization of the array
for(int biz=0;biz<26;biz++)
{
foo[biz]=65+biz; // capital alphabet
}
...
...
//here is searching 1 by 1 iteration(low-yield)
char baz=67; //means we will find 'C'
for(int bar=0;bar<26;bar++)
{
if(foo[bar]==baz) {printf("we found C at the index: %i ",bar);break;}
}
//since this is a soted-array, you can use more-yield search algortihms.
Binary search algortihm(you may use on later chapters):
http://en.wikipedia.org/wiki/Binary_search_algorithm
The use of a multidimensional array is to store both the lower case and upper case alphabets in an array so that they can be mapped. An efficient way is using their ASCII code, but since you are a beginner, I guess this example will introduce you to handle for loops and multidimensional arrays, which I think is the plan of the instructor as well.
Let us first set up the array for the alphabets. We will have two rows with 26 alphabets in each row:
alphabetsEnglish[26][2] = {{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'},
{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}};
Now we can map elements of both cases.
int main()
{
int c,i,j;
char word[10];
printf("Enter a word:");
scanf("%s",word);
c=strlen(word);
printf("Your word has %d letters ", c);
for (i = 0; i < c; i++) //loop for the length of your word
{
for (j = 0; j <= 25; j++) //second loop to go through your alphabet list
{
if (word[i] == alphabetsEnglish[0][j] || word[i] == alphabetsEnglish[1][j]) //check for both cases of your alphabet
{
printf("Your alphabet %c translates to %d: ", word[i], j);
}
}
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *conv(char* str){
static const char* table = "abcdefghijklmnopqrstuvwxyz";
int size, *ret, *p;
if(NULL==str || *str == '\0') return NULL;
size = strlen(str);
ret=p=(int*)malloc(size*sizeof(int));
while(*str){
char *pos;
pos=strchr(table, tolower(*str++));
*p++ = pos == NULL ? -1 : pos - table;
}
return ret;
}
int main(void){
char *word = "abc";
int i, size = strlen(word), *result;
result = conv(word);
for(i=0;i<size;++i){
printf("%d ", result[i]);//0 1 2
}
free(result);
return 0;
}

Resources