-1

Disclaimer: this is for a homework assigment.

Say I have a string that was declared like this:

char *string1;

For part of my program, I need to set string1 equal to another string, string2. I can't use strcpy or use brackets.

This is my code so far:

int i;
for(i = 0; *(string2 + i) != '\0'; i++){
    *(string1 + i) = *(string2 + i);
}

This causes a segmentation fault. According to https://www.geeksforgeeks.org/storage-for-strings-in-c/ , this is because string1 was declared like this: char *string1 and a workaround to avoid segfaults is to use brackets. I can't use brackets, so is there any workaround that I can do?

EDIT: I am also prohibited from allocating more memory or declaring arrays. I cant use malloc(), falloc() etc.

newarsenic
  • 131
  • 1
  • 12
  • First thing you need to do is to allocate memory and assign it to `string1`. – kaylum Sep 16 '20 at 22:11
  • I can't use malloc etc. No other memory allocation is allowed. I'll edit my post to reflect this. – newarsenic Sep 16 '20 at 22:12
  • 2
    `string1 = string2;`? – 001 Sep 16 '20 at 22:13
  • Note: `string1` isn’t a ‘string’, it’s a pointer to a character, and so is `string2`. Hint: two pointers can both point at one character. – DisappointedByUnaccountableMod Sep 16 '20 at 22:14
  • Then where does the memory for the new string come from? You need to tell us more clearly the requirements of the question. There's no way around it - if you need another copy of the string then a different memory buffer is needed (doesn't have to be dynamic memory though). Or are you supposed to modify the original string - again you haven't made that clear because you say "modify" in one place but don't say what needs to be modified and then your code tries to do "copy" not "modify". – kaylum Sep 16 '20 at 22:14
  • There was no mention of a ‘new string’ in the question. – DisappointedByUnaccountableMod Sep 16 '20 at 22:16
  • the new string is given in **argv. I am trying to copy this new string (string2) to string1. I said modify because the geeksforgeeks article said that this is modifying a string literal. – newarsenic Sep 16 '20 at 22:19
  • 1
    Please edit the code as a [mre] in your question so that essential facts like your above comment about ‘argv’ are visible. Any other essential facts? – DisappointedByUnaccountableMod Sep 16 '20 at 22:21
  • 3
    Sorry, your question is still so unclear. Please [edit](https://stackoverflow.com/posts/63928559/edit) the post to provide the full question/task that has been given to you. You may be using the wrong terminology for some things so providing the original question would make it clearer what the actual requirements are. – kaylum Sep 16 '20 at 22:21
  • I hope the answer below helps you fix your code. If you still need help, [edit] your question with code that we can copy/paste and run ourselves to get the exact same error you are struggling with. As your code example stands, we cannot do this because there is no `main()` function and `string1` is not declared. Because of these missing details we are only guessing what the problem is. – Code-Apprentice Sep 16 '20 at 23:14
  • `*(string2 + i)` => `string2[i]` – bolov Sep 16 '20 at 23:36
  • Study arrays, then pointers, then strings. If you do it the other way around, you'll end up very confused. – Lundin Sep 17 '20 at 08:03

2 Answers2

3

The issue you are having is that string2 does not have memory allocated to it.

Your code is missing some details, but I'll assume it looks something like this:

#include <stdio.h>

int main()
{
  char *originalStr = "Hello NewArsenic";
  char *newStr;

  // YMMV depending on the compiler for this line. Might print (null) for
  // newStr or it might throw an error.
  printf("Original: %s\nNew: %s\n", originalStr, newStr);

  int i;
  for (i = 0; *(originalStr + i) != '\0'; i++)
  {
    *(newStr + i) = *(originalStr + i);
  }

  printf("Original: %s\nNew: %s\n", originalStr, newStr);

  return 0;
}

TL;DR Your Issue

Your issue here is that you are attempting to store some values into newStr without having the memory to do so.

Solution

Use malloc.

#include <stdio.h>
#include <stdlib.h> // malloc(size_t) is in stdlib.h
#include <string.h> // strlen(const char *) is in string.h

int main()
{
  char *originalStr = "Hello NewArsenic";

  // Note here that size_t is preferable to int for length.
  // Generally you want to be using size_t if you are working with size/length.
  // More info at https://stackoverflow.com/questions/19732319/difference-between-size-t-and-unsigned-int
  size_t originalLength = strlen(originalStr);

  // This is malloc's typical usage, where we are asking from the system to
  // give us originalLength + 1 many chars.
  // The `char` here is redundant, actually, since sizeof(char) is defined to
  // be one by the C spec, but you might find it useful to see the typical
  // usage of `malloc`.
  // Since malloc returns a void *, we need to cast that to a char *.
  char *newStr = (char *)malloc((originalLength + 1) * sizeof(char));

  // Your code stays the same.
  printf("Original: %s\nNew: %s\n", originalStr, newStr);

  size_t i;
  for (i = 0; *(originalStr + i) != '\0'; i++)
  {
    *(newStr + i) = *(originalStr + i);
  }

  // Don't forget to append a null character like I did before editing!
  *(newStr + originalLength) = 0;

  printf("Original: %s\nNew: %s\n", originalStr, newStr);

  // Because `malloc` gives us memory on the stack, we need to tell the system
  // that we want to free it before exiting.
  free(newStr);

  return 0;
}

The long answer

What is a C String?

In C, a string is merely an array of characters. What this means is that for each character you want to have have, you need to allocate memory.

Memory

In C, there are two types of memory allocation - stack- and heap-based.

Stack Memory

You're probably more familiar with stack-based memory than you think. Whenever you declare a variable, you're defining it on the stack. Arrays declared with bracket notation type array[size_t] are stack-based too. What's specific about stack-based memory allocation is that when you allocate memory, it will only last for as long as the function in which it was declared, as you're probably familiar with. This means that you don't have to worry about your memory sticking around for longer than it should.

Heap Memory

Now heap-based memory allocation is different in the sense that it will persist until it is cleared. This is advantageous in one way:

  • You can keep values of which you don't know the size at compile time. But, that comes at a cost:
  • The heap is slower
  • You have to manually clear your memory once you're done with it.

For more info, check out this thread.

We typically use the function (void *) malloc(size_t) and its sister (void *) calloc(size_t, size_t) for allocating heap memory. To free the memory that we asked for from the system, use free(void *).

Alternatives

You could've also used newStr = originalStr, but that would not actually copy the string, but only make newStr point to originalStr, which I'm sure you're aware of.

Other remarks

  • Generally, it's an anti-pattern to do:
char* string = "literal";

This is an anti-pattern because literals cannot be edited and shouldn't be. Do:

char const* string = "literal";

See this thread for more info.

  • Avoid using int in your loop. Use size_t See this thread.
Marko Vejnovic
  • 45
  • 1
  • 12
2

For part of my program, I need to set string1 equal to another string, string2. I can't use strcpy or use brackets.

Perhaps the solution is just as simple as

string2 = string1

Note that this assignes the string2 pointer to point directly to the same memory as string1. This is sometimes very helpful because you need to maintain the beginning of the string with string1 but also need another pointer to move inside the string with things like string2++.

One way or another, you have to point string2 at an address in memory that you have access to. There are two ways to do this:

  1. Point at memory that you already have access to through another variable either with another pointer variable or with the address-of & operator.

  2. Allocate memory with malloc() or related functions.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268