c pointers in string array - c

I'm trying to copy a char array into another char array using pointer arithmetic. It seems to be correct within the copy() but then I don't understand what happens after it gets to main. char a[] does not get the value of char b[] even if I called the function. Am I missing something? Hehehe
#include <stdio.h>
void copy(char a[], char b[]){
int *apoint = &a;
printf("%d\n", apoint);
printf("%d\n", &a);
*apoint = b;
printf("%d\n", *apoint);
printf("%s\n", a);
printf("%s\n", b);
}
int main(void){
char a[100];
char b[] = "bluhbluh";
copy(a,b);
printf("%d\n", a);
}

That's really not very meaningful C. I suspect it didn't even compile without warnings?
First you take the address of array a, then you take the address of array b, convert it to an integer (without a cast!), and then write that integer into the array a. Then, at the end of main, you try to print the char array as an integer.
Pointer arithmetic doesn't quite work like that. :)
I think you really mean to do something like this:
void copy(char a[], char b[]){
char *ptr_a = a;
char *ptr_b = b;
while (*ptr_b != '\0') {
*ptr_a = *ptr_b;
ptr_a++;
ptr_b++;
}
*ptr_a = '\0';
}
int main(void){
char a[100];
char b[] = "bluhbluh";
copy(a,b);
printf("%s\n", a);
}
Of course, the proper way to do it is like this:
#include <string.h>
int main(void){
char a[100];
char b[] = "bluhbluh";
strncpy(a, b, 100);
printf("%s\n", a);
}

As ams points out in his/her answer, if you want a copy of the array, you need to duplicate each entry. Assuming you don't want to duplicate the array, but instead want a to point at b:
apoint doesn't do anything - it can't change the pointers of a or b. If you wanted to modify the address that a or b pointed to, you'd have to pass the address of them to your function. This won't work, however, as arrays are not pointers - it's why you can't reassign arrays in C. You can modify pointers though - the following is an example of modifying a pointer to a to point at b:
#include <stdio.h>
void redirect(char** a, char* b){
*a = b;
}
int main(void){
char a[100];
char b[] = "bluhbluh";
char* apt = a;
redirect(&apt,b);
printf("a=%s, b=%s", apt,b);
}

apoint should be a char*, don't you have a warning about this pointer assignment?
Moreover you're not iterating on all chars of the string...

Maybe the line int *apoint = &a is wrong, &a is pointer to pointer to char, while apoint is int *. Don't you have compile errors?

You have some major errors in your code specially this line is incorrect int *apoint = &a; it should be char* *apoint = &a;
//Corrected Code:
#include <stdio.h>
void copy(char a[], char b[]){
char* *apoint = &a;
printf("%d\n", apoint);
printf("%d\n", &a);
*apoint = b;
printf("%d\n", *apoint);
printf("%s\n", a);
printf("%s\n", b);
}
int main(void){
char a[100];
char b[] = "bluhbluh";
copy(a,b);
printf("%d\n", a);
}
This will solve the major code issues though I don’t think your copy function would still give your desire results as approach doesn’t seem very right.

Method of copying the char is not good if you enable -Wall or -Werror in gcc you will see so many errors.
The thing you want, which is possible just by copying the pointers in main no need to call copy (a,b);
char *a;
char b[]="bluhbluh"
a=b;
now a started pointing to string "bluhbluh"
But I think that you dont want you want each and every character of array b to be copied into array a
you will have to do like this
void copy(char *a,char *b)
{
while(*b!='\0')
*a++=*b++;
}
int main()
{
char a[100];
char b[]="bluhbluh";
copy(a,b);
printf("%s\n",a);
}

Related

Swap without worrying about the data type

Is that implementation valid and safe to swap two array or variable without worrying about their data type? Or should I use a function pointer?.
This type of code is focusing about using a good implementation of void pointers to swap without worring about the data type.
#include <stdio.h>
#include <string.h>
void swap(void *, void *, int);
int main(void) {
char a[] = "home";
char b[] = "door";
printf("%s %s\n", a, b);
swap(&a, &b, sizeof(a));
printf("%s %s \n", a, b);
return 0;
}
void swap( void *a, void *b, int siz){
char buff[siz]; // I voluntarily omitted dynamic allocation.
memcpy(buff,a,siz);
memcpy(a,b,siz);
memcpy(b,buff,siz);
}
In C, this approach is usually okay (and it's used by standard functions such as qsort()). The contra-indications that indicate you can't use this are when there are any pointers to your objects or their members. Also, take care in multi-threaded code.
Note that in C++, we have std::swap() which will respect user-defined copy/move constructors; copying a C++ object by simply copying its memory is not (in general) valid.
This swap() function is as good/bad as the memcpy() it uses.
If the data structures are just some data structures (of int, float, etc.), it works like a charm.
If you pass two pointers to different structures, all hell will break loose. Offending code:
Foo* myFoo = ...;
Bar* myBar = ...;
swap(myFoo, myBar, sizeof(*myFoo));
Note that your compiler won't complain on this as both pointer types are implicitly convertible to the void*s that swap() expects. But the result of compilation will be bullshit.
If the structure you copy contains a pointer into itself, that pointer will point into the other object after the swap(). The following struct would be an offender of this:
typedef struct {
char* data;
size_t length, allocatedLength;
char shortStringBuffer[32];
} myString;
The idea behind this is, that short strings will be stored in the shortStringBuffer, and data will point to the shortStringBuffer. Strings longer than 31 characters will be stored in dynamically allocated memory, and again be accessible via the data member. It is left as an exercise to the reader to figure out, what precisely happens when you try to copy this thing with a memcpy().
What you must understand, is that memcpy() really only copies bytes, and some data is not invariant to where it is stored. So, each and every use of memcpy() must be accompanied with a proof that it does the correct thing in this particular case. Well, it should. I've never seen such a proof in a comment for some reason...
You can just swap their addresses without further operation to swap two variables/arrays. I tried this and it works:
#include <stdio.h>
int main(void) {
char *a = "home";
char *b = "root";
char *c = a, *d = b;
printf("%s %s\n", a, b);
a = d;
b = c;
printf("%s %s \n", a, b);
return 0;
}
Outputs:
home root
root home
https://ideone.com/MMCOpf
It is safe to use generic pointers to swap, however you must make sure you get the sizes right, and that you don't overflow any array or object:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int swap(void *a, void *b,
size_t a_size, size_t b_size);
int main(void) {
char a[] = "home";
char b[] = "door";
printf("%s %s\n", a, b);
int ret = swap(a, b, sizeof(a), sizeof(b));
if(ret) {
printf("%s %s \n", a, b);
}
return ret;
}
int swap(void *a, void *b,
size_t a_size, size_t b_size)
{
if (b_size != a_size ) {
return 0;
}
void *tmp = malloc(a_size);
if(!tmp) {
return 0;
}
memcpy(tmp, a, a_size);
memcpy(a, b, b_size);
memcpy(b, tmp, a_size);
free(tmp); // tmp no longer needed.
return 1;
}
I solved this by C, code for your reference.
Using uint16_t is neccessary to hold the carry bit when two large uint8_t variables plus.
int main(){
uint8_t tmp[9] = {0x0};
for (int i=9-1; i>=0 ; i--) *(tmp+i) = 0xff-i;
uint16_t tmp2[9];
for (int i=0; i<9; i++) tmp2[i] = tmp[i];
byte_swap_uint8_data(tmp2, 9);
}
void byte_swap_uint8_data(uint16_t* data, int w) {
if (w < 2) return;
for (int i=0; i<w/2; i++) {
data[i] += data[w-1-i];
data[w-1-i] = data[i] - data[w-1-i];
data[i] = data[i] - data[w-1-i];
}
}

Make a function that reads (string) input

I'm new to programming and I have an assignment to make a function that reads a name. For some reason the following 'solution' does not work and the output is always something with weird chinese? characters. What went wrong?
#include <stdio.h>
#include <stdlib.h>
void input(char* a);
int main()
{
char name[8];
input(&name);
printf("%s", name);
return 0;
}
void input(char* a)
{
char buff[8];
scanf("%s", buff);
*a = buff;
}
I think the problem is in your
*a = buff;
statement because buff does not have a life outside of your function. so its memory will be lost.. so it is not safe to try and use buff in this way...
[ But as pointed out by #pablo what *a = buff; will do is copy the address of buff and put it into the memory allocated to a, which is really not what you want to do. ]
below should work and do include return from your function
#include <stdio.h>
#include <stdlib.h>
void input(char* a);
int main()
{
char name[8];
input(&name);
printf("%s", name);
return 0;
}
void input(char* a)
{
// char buff[8];
scanf("%s", a);
// *a = buff;
return;
}
one other point is to check if you are sure the name will only be 8 characters long... why not have it as 50 characters?
First off, you should pass the array to the function input() not its address. Secondly, replace scanf("%s", buff) with scanf("%s", a). This will store the string directly in the array you pass to the function.
So, the fixed code should look like:
#include <stdio.h>
#include <stdlib.h>
void input(char* a);
int main(void)
{
char name[8];
input(name);
printf("%s\n", name);
return 0;
}
void input(char* a)
{
scanf("%s", a);
}
The reason why your code doesn't work is that, you try to assign address of the local array buff to the first element of the array that you pass to the function. This shouldn't even compile or the compiler must issue a warning! If your compiler allows it to pass without any of these, that's a disaster.
Finally, the main function should be declared as int main(void) or int main(int argc, char **argv).
*a = buff; doesn't copy buff to a. Use strcpy() as
strcpy(a,buff);
complete code :
void input(char* a);
int main()
{
char name[8];
//input(&name);/** no need to pass & bcz name itself represents address */
input(name);
printf("[%s]", name);
return 0;
}
void input(char* a) {
char buff[8];
scanf("%s", buff);
//*a = buff; /* not valid **/
strcpy(a,buff);
}
This function is a problem:
void input(char* a)
{
char buff[8];
scanf("%s", buff);
*a = buff;
}
buff is local variable that is only valid while input() is running, so
returning this variable is wrong.
*a = buff; is also wrong. *a is the same as a[0], that means it is a
char. buff is an array of char, so you are assigning a pointer to an array
of char to a char variable. That doesn't sound right, it's putting apples in
the oranges box. In fact what is happening is that you are assigning the address
pointed to by buff in the memory pointed to by a.
Your compiler should have warned you about that, don't ignore the
compiler warnings, they are there to help you, not annoy you,
void input(char *a)
{
scanf("%s", a);
}
would be the correct function.
Doing
char name[8];
input(&name);
is wrong, even though the address of name and &name will be the same, but
they will have different types. name decays into a pointer, so it is a
char*. However &name is a pointer to an array of char, a different type.
The compiler should give you a warning like this:
warning: passing argument 1 of bar from incompatible pointer type
note: expected char * but argument is of type char (*)[8]
The correct call is:
input(name);
In general there is one big problem, though: You only declare 8 spaces for the
buffer. If the name is longer than 7 characters, you will have a buffer
overflow. Instead of using scanf I recommend using fgets instead, because
here you have much more control of the input and the memory boundaries.
char name[30];
fgets(name, sizeof(name), stdin);
name[strcspn(name, "\n")] = 0; // removing possible newline
scanf is not always easy to use. A name can be long and have spaces in it.
Specially for a beginner, this can be tricky. fgets is easier to use.
You don't need to pass the address of name since it's a char array. And when you do the copy in input(), you should use strcpy. The following code works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void input(char* a);
int main()
{
char name[8];
input(name);
printf("%s", name);
return 0;
}
void input(char* a)
{
char buff[8];
scanf("%s", buff);
strcpy(a, buff);
}

Printing a string character-by-character

int main() {
int i;
char a[]={"Hello"};
while(a!='\0') {
printf("%c",*a);
a++;
}
getch();
return 0;
}
Strings are stored in contiguous memory locations & while passing the address to printf() it should print the character. I have jst started learning C. I am not able to find an answer to this. Pls help.
Well a is the name of the array which you cannot increment. It is illegal to change the address of the array.
So define a pointer to a and then increment
#include <stdio.h>
#include <conio.h>
int main()
{
int i;
char a[]="Hello";
char *ptr = a;
while(*ptr!='\0')
{
printf("%c",*ptr);
// a++ here would be illegal
ptr++;
}
getch();
return 0;
}
NOTE:
In fact, arrays in C are non-modifiable lvalues. There are no
operations in C that can modify the array itself (only individual
elements can be modifiable).
In your code, a is a name of an array, you can't modify it like a++. Use a pointer like this:
char *p = "Hello";
while(*p++)
{
printf("%c",*p);
}
Three problems:
char a[]={"Hello"}; is illegal. {"Hello"} can only initialize char* a[]. You probably want char a[]="Hello";
while(a!='\0') - you probably meant *a != '\0'. a is the array itself.
a++; - an array cannot be incremented. you should increment a pointer pointing to it.
You can also try it using a for loop:
#include <stdio.h>
int main(void) {
char a[] = "Hello";
char *p;
for(p = a; *p != '\0'; p++) {
printf("%c", *p);
}
return 0;
}

Returning a string from function

I'm trying to make a substring function on c. It must be return "cdef", but it returns nothing. How can i fix it? Thanks.
#include<stdio.h>
#include<conio.h>
#include<string.h>
char* substring( char *, int, int );
int main(){
char stuff[] = "abcdefghjklmnoprstuvyz";
printf("%s\n", stuff);
printf("%s\n", substring(stuff, 2, 6));
getch();
return 0;
}
char* substring(char *text, int a, int b){
char nText[b-a];
char tmp[2];
strcpy(nText, "");
for(int i=a; i<b; i++){
tmp[0] = text[i];
tmp[1] = '\0';
strcat(nText, tmp);
}
return nText;
}
You are making the mistake of returning a pointer to a variable that may not exist after the function returns. You need to allocate the space in the calling function and just put the result in the space provided, or create permanent space in the function with static. Note - as pointed out by Jonathan Leffler - since the space is "permanent", you can't change the length of the block from one call to the next, and you would have to pick a "sensible" value and test that b-a+1 is not longer than the space allocated. Thus my second method is more robust.
char* substring(char *text, int a, int b){
static char nText[100];
if ((b-a+1)>100) // do something! you can't copy this!
// code
return nText;
}
As Employed Russian pointed out, using a static in this way is in any case quite dangerous since another piece of code might call this function while you're still using the result of the first call. This is NOT ADVISABLE if you do any kind of multi threading, but it's a quick fix if you have a single thread.
A better formulation is
void substring(char *text, int a, int b, char *nText) {
// code, nothing to return
}
In the latter case, you create space in the calling function and pass the pointer to substring. n your main program you would have
char shortString[100];
substring(stuff, 4, 6, shortString);
printf("%s\n", shortString);
As an aside, your method for copying the substring is terribly inefficient. Consider replacing it with
for(int i=a; i<b;i++) nText[i-a]=text[i];
nText[b-a] = '\0';
From this you can see that you actually need to allocate nText[b-a+1] elements, otherwise there is no space for the final '\0'.
Your bug is here:
char* substring(char *text, int a, int b){
char nText[b-a];
...
return nText;
}
The buffer you return becomes invalid as soon as you return from the function.
GCC nicely warns you about this:
t.c:24:5: warning: function returns address of local variable [enabled by default]
How can i fix it?
You have to allocate a new buffer (and the caller will have to free it), or have the caller provide output buffer (as Floris suggested).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* substring( char *, int, int );
char* substringb(char *substr, char *text, int a, int b);
int main(){
char stuff[] = "abcdefghjklmnoprstuvyz";
char substr[5];
printf("%s\n", stuff);
printf("%s\n", substring(stuff, 2, 6));//Things to think to be able to release!
printf("%s\n", substringb(substr, stuff, 2, 6));
getch();
return 0;
}
//dynamic allocate
char* substring(char *text, int a, int b){
char *nText;
nText = (char*)malloc((b-a+1)*sizeof(char));
strncpy(nText, &text[a], b-a);
ntext[b-a] = 0;
return nText;
}
//copy to reserve area
char* substringb(char *substr, char *text, int a, int b){
substr[b-a]=0;
return strncpy(substr, &text[a], b-a);
}

C segmentation fault-char pointers

I need help figuring out why I am getting a segmentation fault here. I have gone over it and I think I am doing something wrong with the pointers, but I can figure out what.
My Program:
#include <stdlib.h>
#include <stdio.h>
void encrypt(char* c);
//characters are shifted by 175
int main(){
char* a;
*a = 'a';
/*SEGMENTATION FAULT HERE!*/
encrypt(a);
printf("test:%c/n",*a);
return 0;
};
void encrypt(char* c){
char* result;
int i=(int)(*c);
i+=175;
if(i>255)
{
i-=256;
}
*c=(char)i;
};
The problem is here:
char *a;
*a = 'a'
Since the variable "a" is not initialized, *a = 'a' is assigning to a random memory location.
You could do something like this:
char a[1];
a[0] = 'a';
encrypt(&a[0]);
Or even just use a single character in your case:
int main(){
char a = 'a';
encrypt(&a);
printf("test:%c/n",a);
return 0;
};
char* a;
*a = 'a';
/*SEGMENTATION FAULT HERE!*/
There isn't any "there" there. You've declared a and left it uninitialized. Then you tried to use it as an address. You need to make a point to something.
One example:
char buffer[512];
char *a = buffer;
(Note buffer has a maximum size and when it falls out of scope you cannot reference any pointers to it.)
Or dynamic memory:
char *a = malloc(/* Some size... */);
if (!a) { /* TODO: handle memory allocation failure */ }
// todo - do something with a.
free(a);
That pointer a does not get the actual space where to store the data. You just declare the pointer, but pointing to where? You can assign memory this way:
char *a = malloc(1);
Then it won't segfault. You have to free the variable afterwards:
free(a);
But in this case, even better,
char a = 'a';
encript(&a);

Resources