#include <stdio.h>
#include<string.h>
void double_string(char ary[])
{
char *start = ary;
// dont exactly know what is happening here nothing is getting printed when consoled
char *end = ary + strlen(ary);
char *org = end;
while(start<org)
{
*end = *start;
start++;
end++;
}
*end = '\0';
}
int main(void) {
char word[255] = {"TACsasasa"};
double_string(word);
printf("%s",word);
return 0;
}
I am unable to understand what is getting stored in character array "*end", I tried printing it but I am not getting any output printed..
char *end = ary + strlen(ary);
This line of code is taking the starting address of the char array in memory, adding the number of bytes inside the array, returned by strlen(), and essentially moving the pointer to the end. The end of the array is the null terminator. Printing that will show nothing as it takes it as an empty string.
Adding an unsigned int (or even a signed int!) is known as pointer arithmetic. It's legal and quite common in C code. You do have to be very careful about going out of the bounds of your memory buffer, though, or you will experience undefined behavior. This is bad. Fortunately, this code appears to be quite well behaved as long as the original string is less than half the length of its memory buffer.
Allow me to try some ASCII art to see if I can make clear what's going on in the double_string function. It starts with this:
char *start = ary;
char *end = ary + strlen(ary);
char *org = end;
At this point, your pointers look like this:
start end
| |
| org
| |
v V
----------------------------------------------------------------------------------
ary | T | A | C | s | a | s | a | s | a |\0 | | | | | | | | | | | ...
----------------------------------------------------------------------------------
Then we have the loop.
while(start<org)
{
*end = *start;
start++;
end++;
}
After the first loop iteration, it looks like this:
start end
| |
| org |
| | |
v V V
----------------------------------------------------------------------------------
ary | T | A | C | s | a | s | a | s | a | T | | | | | | | | | | | ...
----------------------------------------------------------------------------------
Second iteration:
start end
| |
| org |
| | |
v V V
----------------------------------------------------------------------------------
ary | T | A | C | s | a | s | a | s | a | T | A | | | | | | | | | | ...
----------------------------------------------------------------------------------
And so on. The loop continues as long as start is less than (to the left of, in my illustration) org:
start end
| |
org |
| |
V V
----------------------------------------------------------------------------------
ary | T | A | C | s | a | s | a | s | a | T | A | C | s | a | s | a | s | a | | | ...
----------------------------------------------------------------------------------
Now start<org is no longer true, because they're equal. They point to the same location. The loop terminates. All that's left to do is terminate the string with *end = '\0';:
start end
| |
org |
| |
V V
----------------------------------------------------------------------------------
ary | T | A | C | s | a | s | a | s | a | T | A | C | s | a | s | a | s | a |\0 | | ...
----------------------------------------------------------------------------------
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
The community is reviewing whether to reopen this question as of 5 months ago.
Improve this question
I am making a code that reads the data every time a new frequency is applied.
(I have a list of frequencies in an array)
I would like to display at the start of the set of readings a text saying current frequency (Hz): and then the value defined in the following array int freq[] = {1000 , 10000 , 30000 } . I am indexing the different frequencies in a for loop with the following code
for (byte count = 0; count < 6; count = count + 1) {
Serial.print("current Frequency(hz): ");
Serial.println( freq[count], 4);
However when I open the serial monitor I get numbers that I have not defined as a in the freq array. What am I doing wrong.
It takes the 4 least significant bits of cmd and the 10 least significant bits of data and combines them as follows:
cmd data
+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+
... | | | | | ... | | | | | | | | | | |
+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | | | | |
| | | +---------+ | | | | | | | | | |
| | +---------+ | | | | | | | | | | |
| +---------+ | | | | | | | | | | | |
+---------+ | | | | | | | | | | | | |
| | | | | | | | | | | | | |
v v v v v v v v v v v v v v
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 0 | | | | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
data_word
This is how the struct looks like for reference:
struct thread_data {
struct ringbuf_t *rb;
char *file_name;
};
I need to take command line arguments and store it inside struct member variables for each thread_data element in the threads array, like so:
for (int index = optind; index < argc; index++) {
threads[length].rb = rb;
memmove(&threads[length].file_name, &argv[index], strlen(argv[index]));
strcpy(threads[length].file_name, argv[index]);
++length;
}
Prevously used memcpy and it worked when I printed the variable. However, Valgrind is giving me this:
==465645== Source and destination overlap in strcpy(0x1fff000b54, 0x1fff000b54)
==465645== at 0x4C3C180: strcpy (vg_replace_strmem.c:523)
==465645== by 0x400F85: main (bytemincer.c:55)
So I used memmove and I still got the same Valgrind result. Any solution for this?
This is what you want to end up with:
(I'm using "fn" instead of "file_name" in the post.)
*(argv[0]) # 0x2000
+---+---+- -+---+
+--------------->| | | … | 0 |
argv # 0x1000 | +---+---+- -+---+
+---------------+ |
| 0x2000 -------+ *(argv[1]) # 0x2100
+---------------+ +---+---+- -+---+
| 0x2100 -----------+----------->| | | … | 0 |
+---------------+ | +---+---+- -+---+
| 0x2200 -----------)----+
+---------------+ | | *(argv[2]) # 0x2200
| ⋮ | | | +---+---+- -+---+
| +------->| | | … | 0 |
rb # 0x3000 | | +---+---+- -+---+
+---------------+ | |
| 0x4000 -------+ | | *rb # 0x4000
+---------------+ | | | +---------------+
+---)---)------->| |
threads # 0x5000 | | | +---------------+
+---------------+ | | |
| +-----------+| | | |
|rb| 0x4000 --------+ | |
| +-----------+| | | |
|fn| 0x2100 --------)---+ |
| +-----------+| | |
+---------------+ | |
| +-----------+| | |
|rb| 0x4000 --------+ |
| +-----------+| |
|fn| 0x2200 ----------------+
| +-----------+|
+---------------+
| ⋮ |
(This assumes threads is an array rather than a pointer to an array. This doesn't affect the rest of the post.)
All addresses are made up, of course. But you can see how more than once variable have the same address for value. Because it's perfectly fine to have multiple pointers point to the same memory block. All we need to do is copy the pointer (the address).
To copy a pointer, all you need to do is
dst = src;
So all you need is
threads[length].rb = rb;
threads[length].fn = argv[index];
While
memmove(&threads[length].rb, &rb, sizeof(threads[length].rb));
memmove(&threads[length].fn, &argv[index], sizeof(threads[length].fn));
and
memmove(&threads[length].rb, &rb, sizeof(rb));
memmove(&threads[length].fn, &argv[index], sizeof(argv[index]));
are equivalent to the assignments, it doesn't make sense to do something that complicated:
(Note the use of sizeof(argv[index]) rather than strlen(argv[index]). It's the pointer we're copying, so we need the size of the pointer.)
The warning came from trying to copy the string that's in the buffer at 0x2100 into the buffer at 0x2100. Remember that threads[length].fn and argv[index] both have the same value (address) after the memmove.
my google sheet excel document contain data like this
+---+---+---+---+---+---+
| | A | B | C | D | E |
+---+---+---+---+---+---+
| 1 | | c | | x | |
+---+---+---+---+---+---+
| 2 | | r | | 4 | |
+---+---+---+---+---+---+
| 3 | | | | m | |
+---+---+---+---+---+---+
| 4 | | | | | |
+---+---+---+---+---+---+
Column B and D contain data provided by IMPORTRANGE function, which are store in different files.
And i would like to fill column A with first not empty value in row, in other words: desired result must look like this:
+---+---+---+---+---+---+
| | A | B | C | D | E |
+---+---+---+---+---+---+
| 1 | c | c | | x | |
+---+---+---+---+---+---+
| 2 | r | r | | 4 | |
+---+---+---+---+---+---+
| 3 | m | | | m | |
+---+---+---+---+---+---+
| 4 | | | | | |
+---+---+---+---+---+---+
I tried ISBLANK function, but apperantly if column is imported then, even if the value is empty, is not blank, so this function dosn't work for my case. Then i tried QUERY function in 2 different variant:
1) =QUERY({B1;D1}; "select Col1 where Col1 is not null limit 1"; 0) but result in this case is wrong when row contain cells with numbers. Result with this query is following:
+---+---+---+---+---+---+
| | A | B | C | D | E |
+---+---+---+---+---+---+
| 1 | c | c | | x | |
+---+---+---+---+---+---+
| 2 | 4 | r | | 4 | |
+---+---+---+---+---+---+
| 3 | m | | | m | |
+---+---+---+---+---+---+
| 4 | | | | | |
+---+---+---+---+---+---+
2) =QUERY({B1;D1};"select Col1 where Col1 <> '' limit 1"; 0) / =QUERY({B1;D1};"select Col1 where Col1 != '' limit 1"; 0) and this dosn't work at all, result is always #N/A
Also i would like to avoid using nested IFs and javascript scripts, if possible, as solution with QUERY function suits for my case best due to easy expansion to another columns without any deeper knowladge about programming. Is there any way how to make it simply, just with QUERY, and i am just missing something, or i have to use IFs/javascript?
try:
=ARRAYFORMULA(SUBSTITUTE(INDEX(IFERROR(SPLIT(TRIM(TRANSPOSE(QUERY(
TRANSPOSE(SUBSTITUTE(B:G, " ", "♦")),,99^99))), " ")),,1), "♦", " "))
selective columns:
Consider the following code:
#include <stdio.h>
#include <unistd.h>
void foo(char * const arg[]) {
printf("success\n");
}
int main() {
char myargs[2][64] = { "/bin/ls", NULL };
foo(myargs);
execv(myargs[0], myargs);
return 0;
}
Both foo and execv require char * const * argument, but while my foo works (I get success in the output) the system call execv fails.
I would like to know why. Does this have something to do with the implementation of execv?
Also, assuming I have a char** variable - how can I send it to execv?
A two-dimensional array looks like this:
char myargs[2][16];
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| | | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| | | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
I reduced the size from 64 to 16 to keep the diagram from being annoyingly big.
With an initializer, it can look like this:
char myargs[2][16] = { "/bin/ls", "" }
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0| | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0| | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Notice I didn't try to put a null pointer in the second row. It doesn't make sense to do that, since that's an array of chars. There's no place in it for a pointer.
The rows are contiguous in memory, so if you look at a lower level, it's actually more like this:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0| | | | | | | | |\0| | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
When you pass myargs to a function, the famous "array decay" produces a pointer. That looks like this:
void foo(char (*arg)[16]);
...
char myargs[2][16] = { "/bin/ls", "" }
foo(myargs);
+-----------+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| POINTER==|===>| /| b| i| n| /| l| s|\0| | | | | | | | |\0| | | | | | | | | | | | | | | |
+-----------+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
The pointer is arg contains a value which locates the beginning of the array. Notice there is no pointer pointing to the second row. If foo wants to find the value in the second row, it needs to know how big the rows are so it can break down this:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0| | | | | | | | |\0| | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
into this:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0| | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0| | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
That's why arg must be char (*arg)[16] and not char **arg or the equivalent char *arg[].
The exec family of functions doesn't work with this data layout. It wants this:
+-----------+ +-----------+-----------+
| POINTER==|===>| POINTER | NULL |
+-----------+ +-----|-----+-----------+
|
/----------------------/
|
|
| +--+--+--+--+--+--+--+--+
\--->| /| b| i| n| /| l| s|\0|
+--+--+--+--+--+--+--+--+
And when you want to add more arguments, it wants this:
+-----------+ +-----------+-----------+- -+-----------+
| POINTER==|===>| POINTER | POINTER | ... | NULL |
+-----------+ +-----|-----+-----|-----+- -+-----------+
| |
/----------------------/ |
| |
| /--------------------------------/
| |
| |
| | +--+--+--+--+--+--+--+--+
\-+->| /| b| i| n| /| l| s|\0|
| +--+--+--+--+--+--+--+--+
|
| +--+--+--+--+--+--+
\->| /| h| o| m| e|\0|
+--+--+--+--+--+--+
If you compare this to the two-dimensional array diagram, hopefully you can understand why this can't be an implicit conversion. It actually involves moving stuff around in memory.
Both foo and execv require char * const * argument,
Yes.
but while my foo works (I get success in the output) the system call execv fails.
Getting the output you expect does not prove that your code is correct. The call exhibits undefined behavior because its argument does not match the parameter type, but it is plausible that that has little practical effect because the implementation of foo() does not use the parameter in any way. More generally, your code could, in principle, exhibit absolutely any behavior at all, because that's what "undefined" means.
I would like to know why. Does this have something to do with the implementation of execv?
From the standard's perspective, both calls exhibit equally undefined behavior. As a practical matter, however, we know that execv does use its arguments, so it would be much more surprising for that call to produce the behavior you expected than it is for the call to foo to produce the behavior you expected.
The main problem is that 2D arrays are arrays of arrays, and arrays are not pointers. Thus, your 2D array myargs does not at all have the correct type for an argument to either function.
Also, assuming I have a char** variable - how can I send it to execv?
You do not have such a variable in your code, but if you did have, you could cast it to the appropriate type:
char *some_args[] = { "/bin/ls", NULL };
execv((char * const *) some_args);
In practice, most compilers would probably accept it if you omitted the cast, too, although the standard does require it. Best would be to declare a variable that has the correct type in the first place:
char * const correct_args[] = { "/bin/ls", NULL };
execv(correct_args);
Note also that although arrays are not pointers, they are converted to pointers in most contexts -- which I use in the example code -- but only the top level. An array of arrays thus "decays" to a pointer to an array, not a pointer to a pointer.
| |0|1|2|3|4|5|6|7|8|9|
|0| | | | | | | | | | |
|1| | | | | | | | | | |
|2| | | | | | | | | | |
|3| | | | | | | | | | |
|4| | | | | | | | | | |
|5| | | | | | | | | | |
|6| | | | | | | | | | |
|7| | | | | | | | | | |
|8| | | | | | | | | | |
|9| | | | | | | | | | |
I am trying to make a grid that looks like this. I currently keep getting Segmentation Fault Core dumped whenever I try to run the executable. The compiler is also not showing any errors. I am not sure how to print the numbers inside the grid either. Below is the code I currently have (just a part of the whole assignment). Any help is greatly appreciated.
void displayBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Player * player)
{
/* TODO */
int i,j;
char grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2];
for(i = 0; i < BOARD_HEIGHT; i++)
{
for(j = 0; j < BOARD_WIDTH; j++)
{
grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2] = '|';
printf("%c", grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2]);
printf("%s", EMPTY_OUTPUT);
}
printf("\n");
}
}
The BOARD_HEIGHT and BOARD_WIDTH are variables defined in a header file.
#ifndef BOARD_H
#define BOARD_H
#include "helpers.h"
#include "player.h"
#define BOARD_WIDTH 10
#define BOARD_HEIGHT 10
typedef enum cell
{
EMPTY,
BLOCKED,
PLAYER
} Cell;
#define EMPTY_OUTPUT " "
#define BLOCKED_OUTPUT "*"
Cell BOARD_1[BOARD_HEIGHT][BOARD_WIDTH];
Cell BOARD_2[BOARD_HEIGHT][BOARD_WIDTH];
typedef enum playerMove
{
PLAYER_MOVED,
CELL_BLOCKED,
OUTSIDE_BOUNDS
} PlayerMove;
void initialiseBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH]);
void loadBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH],
Cell boardToLoad[BOARD_HEIGHT][BOARD_WIDTH]);
Boolean placePlayer(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Position position);
PlayerMove movePlayerForward(Cell board[BOARD_HEIGHT][BOARD_WIDTH],
Player * player);
void displayBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Player * player);
#endif
this second part is in the header file.
The full code can be found here a1
Your bug is on the line where you index grid beyond the end of the array:
grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2] = '|'; // Bug
This line writes beyond the end of the grid array defined locally as:
char grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2];
Note that the valid indexes into grid[][] go from 0 to BOARD_HEIGHT+1, and 0 to BOARD_WIDTH+1. Your code is accessible one past this in both dimensions.
This results in corrupting the stack, so when the displayBoard function returns, it has corrupted the stack and you get a segmentation fault. Removing this line eliminates the seg fault, but the code still needs work for function correctly.
You should reference the board array, and use indexes i and j, not hardcoded constants.
Here is a working version where I index into the board array, store the current cell value in currentCell, then display it based on a switch statement. This produces the following output given an empty board filled with zeroes:
scott> gcc -g -ogeraldTest -O0 board.c
scott> geraldTest
| |0|1|2|3|4|5|6|7|8|9|
|0| | | | | | | | | | |
|1| | | | | | | | | | |
|2| | | | | | | | | | |
|3| | | | | | | | | | |
|4| | | | | | | | | | |
|5| | | | | | | | | | |
|6| | | | | | | | | | |
|7| | | | | | | | | | |
|8| | | | | | | | | | |
|9| | | | | | | | | | |
Here is the code for main() and printBoard, both in board.c. Note that printBoard is passed the board by value, but it would be better to pass it by reference.
#include <stdio.h>
#include "board.h"
void displayBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Player * player)
{
int i,j;
// First display the header at the top.
printf("| |");
for(j=0; j<BOARD_WIDTH;j++)
printf("%d|",j);
printf("\n");
for(i = 0; i < BOARD_HEIGHT; i++)
{
// Display each row number
printf("|%d|",i);
for(j = 0; j < BOARD_WIDTH; j++)
{
// Bug: grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2] = '|';
Cell currentCell = board[i][j];
switch(currentCell) {
case BLOCKED:
printf("%s",BLOCKED_OUTPUT);
break;
case PLAYER:
printf("P");
break;
default:
printf("%s",EMPTY_OUTPUT);
break;
}
printf("|");
// This code is wrong
// printf("%c|", grid[BOARD_HEIGHT + 2][BOARD_WIDTH + 2]);
// printf("%s", EMPTY_OUTPUT);
}
printf("\n");
}
}
int main(int argc, char ** argv)
{
Cell myBoard[BOARD_HEIGHT][BOARD_WIDTH] = {0};
Player bob = 0;
displayBoard(myBoard, &bob);
}
I took your board.h and defined the missing types in order to get it to compile. You can likely just use your own headers as is.
#ifndef BOARD_H
#define BOARD_H
// #include "helpers.h"
// #include "player.h"
#define BOARD_WIDTH 10
#define BOARD_HEIGHT 10
typedef int Boolean; // Added
typedef int Player; // Added
typedef struct { // Added
int row;
int col;
} Position;
typedef enum cell
{
EMPTY,
BLOCKED,
PLAYER
} Cell;
#define EMPTY_OUTPUT " "
#define BLOCKED_OUTPUT "*"
Cell BOARD_1[BOARD_HEIGHT][BOARD_WIDTH];
Cell BOARD_2[BOARD_HEIGHT][BOARD_WIDTH];
typedef enum playerMove
{
PLAYER_MOVED,
CELL_BLOCKED,
OUTSIDE_BOUNDS
} PlayerMove;
void initialiseBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH]);
void loadBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH],
Cell boardToLoad[BOARD_HEIGHT][BOARD_WIDTH]);
Boolean placePlayer(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Position position);
PlayerMove movePlayerForward(Cell board[BOARD_HEIGHT][BOARD_WIDTH],
Player * player);
void displayBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Player * player);
#endif