While executing the below code:
int main()
{
int abc[3][3]={0};
for(int *ip=&abc[0][0];ip<=&abc[3][3];ip++)
{
printf("%d \n",*ip);
}
}
Expected result is 9 zeros but it displays 12 data. What might be reason?
If you look at the memory layout of a 3x3 array, it looks like:
[0][0] [1][0] [2][0]
+----+----+----+----+----+----+----+----+----+
| | | | | | | | | |
+----+----+----+----+----+----+----+----+----+
Where is the element [3][3]?
[0][0] [1][0] [2][0] [3][0] [3][3]
+----+----+----+----+----+----+----+----+----+----+----+----+----+
| | | | | | | | | | | | | |
+----+----+----+----+----+----+----+----+----+----+----+----+----+
That explains why you end up accessing 12 elements.
Your code is subject to undefined behavior for accessing the beyond valid indices but that's another issue.
You could use:
for (int *ip = &abc[0][0]; ip <= &abc[2][2]; ip++)
{
printf("%d \n",*ip);
}
However, it is better to access a 2D array as a 2D array.
for (size_t i = 0; i < 3; ++i )
{
for (size_t j = 0; j < 3; ++j )
{
printf("%d \n", abc[i][j]);
}
}
I am trying to write this function that takes an array input and assigns random numbers between 1-52 to the array. Then prints back the numbers. I get an error message on the 4th line that says expression is not assignable. Is my use of pointers incorrect or is it not possible to add content to array with pointers?
void shuffleDeck(int *deck[]) {
int i;
for(i=0;i<=52;i++)
rand()%53 = deck[i]; // I get an error message on this line
}
int main() {
srand(time(NULL));
int deck[2000];
shuffleDeck(deck);
int i;
for(i=0;i<=52;i++){
printf("%d", deck[i]);
}
return 0;
}
Assigment direction is from right to left
So in this expression
deck[i] = rand()%52 + 1;
First is called function rand()
Then the result of function %52
Then 1 is added
And finnally its assigned to deck[i]
Array (what you have in main) is
0 1 2 3 4
+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+
^-------------------------- arr[0]
While Array of pointers (what your function expects) is
0 1 2 3 4
+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 0
+---+---+---+---+---+
------^
| +---+---+---+---+---+
| | 0 | 0 | 0 | 0 | 0 | 1
| +---+---+---+---+---+
| +---+---+---+---+---+
| | 0 | 0 | 0 | 0 | 0 | 2
| +---+---+---+---+---+
|
----------------------------- arr[0][0]
When array is passed to function, then arr[] and *arr are the same. But only as function arguments!
%53 returns 0-52,so if you need 1-52, use %52 + 1 (0-51 + 1 = 1-52)
If you cant solve it, here is code with fixed bugs.
void shuffleDeck(int deck[]) {
int i;
for(i=0;i<=52;i++)
deck[i] = rand()%52 + 1;
}
int main() {
srand(time(NULL));
int deck[2000];
shuffleDeck(deck);
int i;
for(i=0;i<=52;i++){
printf("%d", deck[i]);
}
return 0;
}
char command [][12] = {
{"Attention!!"},
{"About Turn!"},
{"Left Turn!"},
{"right Turn!"},
{"Dismiss!"}
};
int i;
for (i=1; i<5; i++)
{
strcat (command [0], command [i]);
}
printf ("length of command[0]:%ld\nNew string:%s\n", strlen(command[0]), command[0]);
In the above block of code, do I need to check destination string command[0] to see if it has enough space for the other 4 strings?
I didn't do that but it turns out the compiler didn' t report any error and printed out the concatenated string.
Is it ok to do it like this with a for loop?
Yes, you do need to consider the space available in the target string
when using strcat(). In fact, you need to consider the available
space for all string manipulation operations. If you don't know that
there is enough space, you are not safe.
Consider the array:
char command[][12] =
{
{"Attention!!"},
{"About Turn!"},
{"Left Turn!"},
{"Right Turn!"},
{"Dismiss!"}
};
The memory for the array looks like this, using $ to represent '\0'
+---+---+---+---+---+---+---+---+---+---+---+---+
| A | t | t | e | n | t | i | o | n | ! | ! | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+
| A | b | o | u | t | | T | u | r | n | ! | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+
| L | e | f | t | | T | u | r | n | ! | $ | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+
| R | i | g | h | t | | T | u | r | n | ! | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+
| D | i | s | m | i | s | s | ! | $ | $ | $ | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+
The specification of strcat() says:
The strcat function appends a copy of the string pointed to by s2
(including the terminating null character) to the end of the string
pointed to by s1. The initial character of s2 overwrites the null
character at the end of s1. If copying takes place between objects
that overlap, the behavior is undefined.
Your processing loop is:
for (int i = 1; i < 5; i++)
{
strcat(command[0], command[i]);
}
It is fairly clear that you are invoking undefined behaviour because the
extended material in command[0] runs over the content of command[1].
Nevertheless, some common implementations will actually behave sensibly,
but there is no guarantee that every implementation will.
Indeed, when run on macOS Sierra 10.12.2 with GCC 6.3.0, the first
iteration of the loop generates an Abort trap: 6 error. This is a
perfectly legitimate result of 'undefined behaviour'.
However, if we 'reimplement' strcat() to behave as you might expect,
what you end up with is:
+---+---+---+---+---+---+---+---+---+---+---+---+
| A | t | t | e | n | t | i | o | n | ! | ! | A |
+---+---+---+---+---+---+---+---+---+---+---+---+
| b | o | u | t | | T | u | r | n | ! | L | e |
+---+---+---+---+---+---+---+---+---+---+---+---+
| f | t | | T | u | r | n | ! | R | i | g | h |
+---+---+---+---+---+---+---+---+---+---+---+---+
| t | | T | u | r | n | ! | D | i | s | m | i |
+---+---+---+---+---+---+---+---+---+---+---+---+
| s | s | ! | $ | i | s | s | ! | $ | $ | $ | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+
Demonstration code
#include <ctype.h>
#include <stdio.h>
#include <string.h>
static inline void n_strcat(char *s1, char *s2)
{
memmove(s1 + strlen(s1), s2, strlen(s2) + 1);
}
#ifndef USE_REAL_STRCAT
#undef strcat
#define strcat(s1, s2) n_strcat(s1, s2)
#endif /* USE_REAL_STRCAT */
static void print_bar(int cols)
{
printf(" +");
for (int i = 0; i < cols; i++)
printf("---+");
putchar('\n');
}
static void print_cmd(int rows, int cols, char cmd[rows][cols])
{
print_bar(cols);
for (int i = 0; i < rows; i++)
{
printf(" |");
for (int j = 0; j < cols; j++)
{
unsigned char u = cmd[i][j];
if (!isprint(u))
u = '$';
printf(" %c |", u);
}
putchar('\n');
print_bar(cols);
}
}
int main(void)
{
char command[][12] =
{
{ "Attention!!" },
{ "About Turn!" },
{ "Left Turn!" },
{ "Right Turn!" },
{ "Dismiss!" },
};
enum { CMD_ROWS = sizeof(command) / sizeof(command[0]) };
enum { CMD_COLS = sizeof(command[0]) / sizeof(command[0][0]) };
print_cmd(CMD_ROWS, CMD_COLS, command);
for (int i = 1; i < 5; i++)
strcat(command[0], command[i]);
printf("\nLength of command[0]: %zu\nNew string: [%s]\n\n", strlen(command[0]), command[0]);
print_cmd(CMD_ROWS, CMD_COLS, command);
return 0;
}
The output from the program is the two tables shown above, with this information in between:
Length of command[0]: 51
New string: [Attention!!About Turn!Left Turn!Right Turn!Dismiss!]
I am writing a program that allows a user to play the game connect four against the computer. I am having trouble printing out the correct dimensions for the board. I tried using nested for loops, but the output is a little off.
Here is a part of my code:
#include <stdio.h>
#define BOARD_SIZE_VERT 6
#define BOARD_SIZE_HORIZ 7
void display_board(int board[] [BOARD_SIZE_VERT]);
int main ()
{
int board[BOARD_SIZE_HORIZ][BOARD_SIZE_VERT] = {{0}};
display_board(board);
return 0;
}
void display_board(int board[] [BOARD_SIZE_VERT])
{
int i,j;
for (i=0; i<BOARD_SIZE_HORIZ; i++) {
printf ("+---+---+---+---+---+---+---+");
printf ("\n");
for (j=0; j<BOARD_SIZE_VERT; j++)
printf ("| ");
printf("\n");
}
}
This is my output:
+---+---+---+---+---+---+---+
| | | | | |
+---+---+---+---+---+---+---+
| | | | | |
+---+---+---+---+---+---+---+
| | | | | |
+---+---+---+---+---+---+---+
| | | | | |
+---+---+---+---+---+---+---+
| | | | | |
+---+---+---+---+---+---+---+
| | | | | |
+---+---+---+---+---+---+---+
| | | | | |
And this is what I want it to look like:
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
void display_board(int board[] [BOARD_SIZE_VERT]){
int i,j;
for (i=0; i<BOARD_SIZE_VERT; i++) {
printf ("+");
for (j=0; j<BOARD_SIZE_HORIZ; j++)
printf("---+");
printf ("\n");
printf ("|");
for (j=0; j<BOARD_SIZE_HORIZ; j++)
printf(" |");
printf ("\n");
}
printf ("+");
for (j=0; j<BOARD_SIZE_HORIZ; j++)
printf("---+");
printf ("\n");
}
Two main problems: your loops are inverted, and you need some extra characters printed to to get the extra lines on the bottom and right. Try this:
void display_board(int board[] [BOARD_SIZE_HORIZ])
{
int row,col;
for (row=0; row<BOARD_SIZE_VERT; row++) {
printf ("+---+---+---+---+---+---+---+");
printf ("\n");
for (col=0; col<BOARD_SIZE_HORIZ; col++) {
printf ("| ");
}
printf("|\n");
}
printf ("+---+---+---+---+---+---+---+");
}
Here are the relevant changes:
I swapped the usage of the VERT/HORIZ constants in the loops. The outer loop controls the height of the board since you are printing one line at a time. The inner loop controls the number of columns in the board
Renamed i and j to the row and col so the code is more self-documenting
Added a pipe to the printf("\n"), because you need one more vertical separator line than the actual number of slots for each line
Added an extra printf("+---.... at the end, because you need one more horizontal separator than the actual number of rows
Also, I changed the array definition in the function prototype so that the first index is the row and the second is the column. If you choose to follow that, you would need to change other usages of the array in your code. For example:
int board[BOARD_SIZE_VERT][BOARD_SIZE_HORIZ] = {{0}};
Your code work very well. But you have eight "| " to display and You loops only BOARD_SIZE_VERT which worth 6. So you should increase it to 8 or add to it. Try this:
void display_board(int board[] [BOARD_SIZE_VERT]){
int i,j;
for (i=0; i<BOARD_SIZE_HORIZ - 1; i++) {
printf ("+---+---+---+---+---+---+---+");
printf ("\n");
for (j=0; j<BOARD_SIZE_VERT + 2; j++)
printf ("| ");
printf("\n");
}
printf ("+---+---+---+---+---+---+---+\n");
}
Playing with pointers in C is fun (not really).
I have several arrays of strings I want to declare in an easy way, preferably something like:
arrayOfStrings1 = {"word1", "word2", etc. };
arrayOfStrings2 = {"anotherword1", "anotherword2", etc. };
arrayOfStrings3 = etc.
etc.
Something similar to a translation array (but not quite), so I want to be able to swap between these during runtime. For that I want a pointer pointerToArrayOfStrings that I can swap like:
pointerToArrayOfStrings = arrayOfStrings1;
doStuff();
pointerToArrayOfStrings = arrayOfStrings2;
doSomeOtherStuff();
In my naive understanding of arrays of strings and pointers to these, this is what I tried:
// Danish transforms
const unsigned char* da_DK[] = {"b","bb","c","c","cc","d","dd","e","f","ff","g","gg","h","hh","j","j","jj","k","k","kk","l","l","l","l","ll","m","mm","n","n","nn","p","pp","r","r","r","rr","s","s","s","ss","t","t","tt","v","v","vv","æ"};
// British english transforms
const unsigned char* en_GB[] = {"a","a","a","a","a","a","a","a","a","a","a","a","a","age","ai","aj","ay","b","cial","cian","cian","dj","dsj","ea","ee","ege","ei","ei","eigh","eigh","f","f","f","g","g","gs","i","i","i","j","j","k","ks","kw","l","m","n","n","o","r","s","s","sd","sdr","sion","sion","sj","sj","tial","tion","tion","tj","u","u","u","u","w","ye","ye","z"};
// More languages....
const unsigned char** laguageStrings;
// Assign language
if (streq(language, "da-DK")){
laguageStrings= da_DK;
}
else if (streq(language, "en-GB")){
laguageStrings= en_GB;
}
else
return 0;
}
Language is a char * containing the language "en-GB", "da-DK" etc., streq() is just a home brewed (somewhat faster than strcmp()) string comparison function.
Long story short, depending on compiler this approach may work, report compiler warnings or compile, but give unexpected results.
What would be the correct way to solve this problem?
There are two way of working with array of characters (strings) in C. They are as follows:
char a[ROW][COL];
char *b[ROW];
Pictorial representation is available as an inline comment in the code.
Based on how you want to represent the array of characters (strings), you can define pointer to that as follows
char (*ptr1)[COL] = a;
char **ptr2 = b;
They are fundamentally different types (in a subtle way) and so the pointers to them is also slightly different.
The following example demonstrates the different ways of working with strings in C and I hope it helps you in better understanding of array of characters (strings) in C.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ROW 5
#define COL 10
int main(void)
{
int i, j;
char a[ROW][COL] = {"string1", "string2", "string3", "string4", "string5"};
char *b[ROW];
/*
a[][]
0 1 2 3 4 5 6 7 8 9
+---+---+---+---+---+---+---+------+---+---+
| s | t | r | i | n | g | 1 | '\0' | | |
+---+---+---+---+---+---+---+------+---+---+
| s | t | r | i | n | g | 2 | '\0' | | |
+---+---+---+---+---+---+---+------+---+---+
| s | t | r | i | n | g | 3 | '\0' | | |
+---+---+---+---+---+---+---+------+---+---+
| s | t | r | i | n | g | 4 | '\0' | | |
+---+---+---+---+---+---+---+------+---+---+
| s | t | r | i | n | g | 5 | '\0' | | |
+---+---+---+---+---+---+---+------+---+---+
*/
/* Now, lets work on b */
for (i=0 ; i<5; i++) {
if ((b[i] = malloc(sizeof(char) * COL)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
}
strcpy(b[0], "string1");
strcpy(b[1], "string2");
strcpy(b[2], "string3");
strcpy(b[3], "string4");
strcpy(b[4], "string5");
/*
b[] 0 1 2 3 4 5 6 7 8 9
+--------+ +---+---+---+---+---+---+---+------+---+---+
| --|------->| s | t | r | i | n | g | 1 | '\0' | | |
+--------+ +---+---+---+---+---+---+---+------+---+---+
| --|------->| s | t | r | i | n | g | 2 | '\0' | | |
+--------+ +---+---+---+---+---+---+---+------+---+---+
| --|------->| s | t | r | i | n | g | 3 | '\0' | | |
+--------+ +---+---+---+---+---+---+---+------+---+---+
| --|------->| s | t | r | i | n | g | 4 | '\0' | | |
+--------+ +---+---+---+---+---+---+---+------+---+---+
| --|------->| s | t | r | i | n | g | 5 | '\0' | | |
+--------+ +---+---+---+---+---+---+---+------+---+---+
*/
char (*ptr1)[COL] = a;
printf("Contents of first array \n");
for (i=0; i<ROW; i++)
printf("%s \n", *ptr1++);
char **ptr2 = b;
printf("Contents of second array \n");
for (i=0; i<ROW; i++)
printf("%s \n", ptr2[i]);
/* b should be free'd */
for (i=0 ; i<5; i++)
free(b[i]);
return 0;
}
What would be the correct way to solve this problem?
Well, the correct way would be to use a library specifically designed for dealing with multilanguage interfaces - for instance gettext.
Another way, though patchier, would be to use a hash table (also known as "dictionary" or "hash map" or "associative map" in other languages/technologies): Looking for a good hash table implementation in C
It's probably not the answer you were looking for, but you've asked the wrong question to the right problem.