How to copy integer array contents to a character pointer? - c

I have a character pointer , char *buf;
I have a array of integers , int console_buffer[256];
I need to copy the console_buffer contents to character buf.
How do I do this? The buf and console_buffer are part of different structures.

Going by your comment,
buf = malloc(256); // 257 if console_buffer may be full without EOF
/* if you want to allocate just as much space as needed, locate the EOF in console_buffer first */
for(int i = 0; i < 256 && console_buffer[i] != -1; ++i){
buf[i] = (char)console_buffer[i];
}

If you already allocated the memory for buf, and if each integer is between 0 and 9, you can do:
for(int i = 0; i < 256; i++)
{
buf[i] = '0' + console_buffer[i]; /* convert 1 to '1', etc. */
}
If the integers are larger than 9, you can use the sprintf function.
Reading your new comment, perhaps you can also achieve your goal by reading from console buffer directly to an array of chars until you have -1 (check by integers comparison, or by strcmp, or by comparing the 2 last characters to 0 and to 1).

I think this is a better way to convert values to chars
int i = 0;
while (i <= 256) {
buf[i] = (char) console_buffer[i];
i++;
}

Related

How to reset a string in C

I have this string
char currentString[212] = { 0 };
and after I'm using it once, I want to reset it.
I tried many ways, such as:
for (int k = 0; k < strlen(currentString); k++)
{
currentString[k] = '\0';
}
but it won't go over the loop more than once, and it give '\0' only to the first char, the rest remain the same.
and I also tried:
currentString[0] = '\0';
yet I get the same result.
any suggestions for what can I do?
thanks!
strlen will find the length by searching for the first occurrence of \0. So if you want to reset the whole array, you should change strlen(currentString) to sizeof currentString. However, do note that this will not work with pointers.
If you pass the array to a function, you cannot determine the size of the array afterwards, so this will not work:
void foo(char * arr) {
for (int k = 0; k < sizeof arr; k++)
arr[k] = '\0';
}
Instead you need to do like this:
void foo(char * arr, size_t size) {
for (int k = 0; k < size; k++)
arr[k] = '\0';
}
But of course there's no reason to write custom functions for this when memset is available.
Imagine char currentString[] = "abc"; and then running you loop:
k = 0
initialy strlen(currentString) = 3, there are 3 characters before '\0' byte. the loop condition k < strlen(currentString) is true
k = 0 -> currentString[0] = '\0'
k++ -> k = 1
then strlen(currentString) = 0 (as the first byte of currentString is equal to '\0', there are no characters before '\0')
the loop condition is false k < strlen(currentString) -> 1 < 0
So the loop will always run only one time.
If you want to write only zero bytes to a memory region, use memset
memset(currentString, 0, sizeof(currentString));
will set the memory region as pointed to by currentString pointer with sizeof(currentString) bytes to zeros.
Setting the first byte to zero:
currentString[0] = '\0';
maybe considered enough to "clear a string".
Setting the first byte to '\0' wont clear out the currentString.You may think that because ANSI C thinks that is a string terminator and if you print your string it will show empty.But if you check the second byte you will see the second char from your string. As other's said the best option to wipe out the string is:
memset(currentString, 0, sizeof(currentString));
And is way safer and faster.Also in ANSI C 0 and '\0' are the same.
to zero the whole array
char arr[SOMESIZE];
/* ... */
memset(arr, 0, sizeof(arr));
pointer - you need to know the size of the allocated memory as sizeof will return the size of the pointer itself only, not the referenced object;
char *p = malloc(SIZE);
/* ..... */
memset(p, 0 , SIZE);
It is never a good decision to calculate anything again and again. Instead you should calculate the strlen() only once.
That being said, in your case, doing so will solve the problem, as the reason it didn't work was that strlen() returned 0 right after the first round, since the length of the string became 0.
int n = strlen(currentString);
for (int k = 0; k < n; k++)
{
currentString[k] = '\0';
}

Using C (syscall) to write an integer matrix into a text file?

So, I have my matrix, let's say
int matC[N][N],
which is already filled with integer values.
What I have to do is to save this matrix into a .txt file.
I've tried this:
1: convert the integers contained in the matrix into a string
char *buffer;
for (int i = 0 ; i < N ; i++)
{
for (int j = 0 ; j < N ; j++)
{
snprintf(buffer, sizeof(matC[i][j]), "%d", matC[i][j]);
}
}
2: write the string in a file (fileC.txt)
int fdC = open("fileC.txt", O_RDWR);
write(fdC, buffer, sizeof(buffer));
I do get something in my fileC.txt, but it's some sort of bunch of unintelegible symbols.
Thanks in anticipation for any help.
A few things.
First, you need to allocate memory for your buffer. sizeof(buffer) will be the size of a pointer, not the buffer length, so you you store that in buf_len. Depending on how many digits the numbers in your matrix are, you might need more or less space in your buffer.
Then, you don't want to write to the beginning of buffer with each snprintf call, but strchr(buffer, '\0') will return a pointer to the spot you want to write to. The second argument should be the length of the buffer from the spot you're currently at, which is buf_len - strlen(buffer).
Finally, you only want to write strlen(buffer) bytes to the file so you don't write random bytes to your file.
char *buffer;
int buf_len = 100;
buffer = (char*)malloc(buf_len);
buffer[0] = '\0';
for (int i = 0 ; i < N ; i++)
{
for (int j = 0 ; j < N ; j++)
{
snprintf(strchr(buffer, '\0'), buf_len - strlen(buffer), "%d", matC[i][j]);
}
}
int fdC = open("fileC.txt", O_RDWR);
write(fdC, buffer, strlen(buffer));
free(buffer);

Replace a subarray with a character in C

I have an array and I need to replace a subarray from this array with a character.
unsigned char * data = {'a','b','c','d','e'};
I need to delete 'a','b''c' and insert 'R'
The final array will be: unsigned char * data = {'R','d','e'};
With only 3 elements.
How can I do that in C?
You say you think of data as an array, therefore it is better that you declare data as an array instead of a pointer. (The way your code is now you have a pointer that is initialized incorrectly by casting the character 'a' to a char * pointer. That way it will not be pointing anywhere.)
You can replace characters by assigning to elements of the array, and you can shift parts of the data in the array using memmove.
Which means that maybe you want something like this:
unsigned char data[] = {'a','b','c','d','e'};
data[0] = 'R';
memmove(data + 1, data + 3, sizeof(data) - 3);
The memmove call moves sizeof(data) - 3 bytes of data from address data + 3 to address data + 1. The function memmove even works when the regions of memory between which you are moving bytes of data overlap.
If you then print the relevant part of your data:
fwrite(data, 1, sizeof(data) - 2, stdout);
putchar('\n');
This will get you the output:
Rde
However, notice that the size of the array will not have changed. It still will be five characters long. So replacing abc by something longer than three characters will not work like this. Also, this array is not a null-terminated string, which is the more usual way to have sequences of characters in C.
If you prefer to use a string "abcde" instead of what you are doing now (but then why call it "data"?), add a comment below this answer, and I'll extend it.
for(int i = 0; i < 5; i++){
if (data[i] > 96 && data[i] < 100) data[i] = 'R';
}
How about the following way?
unsigned char * data = {'a','b','c','d','e'};
int length = strlen(data);
unsigned char * output = (unsigned char *)malloc(sizeof(unsigned char)*length);
for(int i = 0, j =0; i < length; i++, j++){
if (i+2 < length && data[i] == 'a' && data[i+1] == 'b && data[i+2] == 'c') {
output[j]='R';
i++;
i++;
}
else
output[j]=data[i];
}

How to check if an array of characters is a valid integer >= 1 in c?

I don't know the size of the array and using isdigit(array[i]) for every element i < sizeof(array) doesn't seem to work correctly.
I am trying to:
Check that every char is a digit.
Convert the string to int.
Check that it is > 0
int all_digits(char *string){
short i;
for(i=0; i < sizeof(string); i++){
if (!isdigit(string[i])){
//Non-digit found.
return 1;
}
}
//All of them are digits.
return 0;
}
The first part is the one that I can't get.
int n = strlen(string);
for(i=0; i < n; i++)
sizeof(pointer) is not same as sizeof(array)
You need to pass a valid string which is a null terminated string else strlen() might crash.
Edits:
Alternatively you can have
for(i=0; string[i] != '\0'; i++)
In this case you cannot get the correct length using the sizeof function.
sizeof function will give you the size of the given data type. You can use the
strlen function.
While using the strlen you have to manage the following,
Consider in your string in last there is no null value you didn't get the correct value of the string length. For this you have to send the size of that array as a another parameter or you have to place the null value in the last value of the a string.
Then you can get that easily.
In your code, string is of type char *. sizeof(string) will give you the size of a char *, not the array.
You need to pass the size of the array explicitly, using another paramter to all_digits() function and use that value in for loop condition checking.
Maybe something like this
int all_digits(char *string, int size){
short i;
for(i=0; i < size; i++){
if (!isdigit(string[i])){
//Non-digit found.
return 1;
}
}
//All of them are digits.
return 0;
}
Note: Specifically in case of a char *, a better, smaller and cleaner approach to this can be achieved using strlen() [assuming proper aguments passed], which will give you the length of the supplied string.
Simply iterate along the string, testing every character:
int all_digits(char *string){
if( *string == 0) // empty string - wrong
return 1;
for( ; *string != 0; string++) // scan the string till its end (a zero byte (char)0)
if (!isdigit(*string)) // test for a digit
return 1; // not a digit - return
return 0; // all characters are digits
}
However that only tests if the string consists of digits and does not make you any closer to determining its numerical value...

How to use strncpy with a for-loop in C?

I am writing a program which will take every 3 numbers in a file and convert them to their ASCII symbol. So I thought I could read the numbers into a character array, and then make every 3 elements 1 element in a second array, convert them to int and then print these as char.
I am stuck on taking every 3 elements, however. This is my code snippet for this part:
char arry[] = "073102109109112"; <--example string read from a file
char arryNew[16] = {0};
for(int i = 0; i <= sizeof(arryNew); i++){
strncpy(arryNew, arry, 3);
arryNew[i+3]='\0';
puts(arryNew);
}
What this code gives me is the first 3 numbers, fifteen times. I've tried incrementing i by 3, which gives me the first 3 numbers 5 times. How do I write a for-loop with strncpy so that after copying n chars, it moves to the next n chars?
You pass always the pointer to the beginning of the array, so you will always have the same result of course. You must include the loop counter to get at the next block:
strncpy(arryNew, &arry[i*3], 3);
Here you have a problem:
arryNew[i+3]='\0';
First of all, you don't need to set the null byte every time, because this will not change anyway. Additionally you will corrupt memory, because you use i+3 as the index so when you reach 14 and 15, it will write beyond the arrayboundary.
Your arrayNew must be longer, because your original array is 16 characters, and your target array is also. If you intend to have several 3char strings in there, then you must have 5*4 characters for your target, because each string also has the 0-byte.
And of course, you must also use the index here as well. The way it is written now, it will write beyond the array boundary, when i reaches 14 and 15.
So what you seem to want to do (not sure from your description) is:
char arry[] = "073102109109112"; <--example string read from a file
char arryNew[20] = {0};
for(int i = 0; i <= sizeof(arry); i++)
{
strncpy(&arryNew[i*4], &arry[i*3], 3);
puts(&arryNew[i*4]);
}
Or if you just want to have the individual strings printed then you can just do:
char arry[] = "073102109109112"; <--example string read from a file
char arryNew[4] = {0};
for(int i = 0; i <= sizeof(arry); i++)
{
strncpy(arryNew, &arry[i*3], 3);
puts(arryNew);
}
Making things a bit simpler: your target string doesn't change.
char arry[] = "073102109109112"; <--example string read from a file
char target[4] = {0};
for(int i = 0; i < strlen(arry) - 3; i+=3)
{
strncpy(target, arry + i, 3);
puts(target);
}
Decoding:
start at the beginning of arry
copy 3 characters to target
(note the fourth element of target is \0)
print out the contents of target
increment i by 3
repeat until you fall off the end of the string.
Some problems.
// Need to change a 3 chars, as text, into an integer.
arryNew[i] = (char) strtol(buf, &endptr, 10);
// char arryNew[16] = {0};
// Overly large.
arryNew[6]
// for(int i = 0; i <= sizeof(arryNew); i++){
// Indexing too far. Should be `i <= (sizeof(arryNew) - 2)` or ...
for (i=0; i<arryNewLen; i++) {
// strncpy(arryNew, arry, 3);
// strncpy() can be used, but we know the length of source and destination,
// simpler to use memcpy()
// strncpy(buf, a, sizeof buf - 1);
memcpy(buf, arry, N);
// arryNew[i+3]='\0';
// Toward the loop's end, code is writing outside arryNew.
// Lets append the `\0` after the for() loop.
// int i
size_t i; // Better to use size_t (or ssize_t) for array index.
Suggestion:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char Source[] = "073102109109112"; // example string read from a file
const int TIW = 3; // textual integer width
// Avoid sprinkling bare constants about code. Define in 1 place instead.
const char *arry = Source;
size_t arryLen = strlen(arry);
if (arryLen%TIW != 0) return -1; // is it a strange sized arry?
size_t arryNewLen = arryLen/TIW;
char arryNew[arryNewLen + 1];
size_t i;
for (i=0; i<arryNewLen; i++) {
char buf[TIW + 1];
// strncpy(buf, a, sizeof buf - 1);
memcpy(buf, arry, TIW);
buf[TIW] = '\0';
char *endptr; // Useful should OP want to do error checking
// TBD: test if result is 0 to 255
arryNew[i] = (char) strtol(buf, &endptr, 10);
arry += TIW;
}
arryNew[i] = '\0';
puts(arryNew); // prints Ifmmp
return 0;
}
You could use this code to complete your task i.e. to convert the given char array in form of ascii value.
char arry[] = "073102109109112";
char arryNew[16] = {0};
int i,j=0;
for(i = 0; i <= sizeof(arryNew)-2; i+=3)
{
arryNew[j]=arry[i]*100+arry[i+1]*10+arry[i+2]*1;
j++;
arryNew[j+1]='\0';
puts(arryNew);
}

Resources