0

I was doing a relatively simple string problem in UVa's online judge to practice with strings since I've been having a hard time with them in C. The problem basically asks to check if a string B contains another string A if you remove the 'clutter' and concatenate the remaining characters, for example if "ABC" is contained in "AjdhfmajBsjhfhC" which in this case is true.

So, my question is how can I efficiently allocate memory for a string which I don't know its length? What I did was to make a string really big char Mstring[100000], read from input and then use strlen(Mstring) to copy the string the a properly sized char array. Something like :

char Mstring[100000];

scanf("%s",Mstring);
int length = strlen(Mstring);
char input[length+1]={0};
for(int i = 0; i<length;i++){
    input[i]=Mstring[i];
}

Is there a better/standard way to do this in C? I know that C does not has a great support for strings, if there is not a better way to do it in C maybe in C++?

Darwin57721
  • 177
  • 1
  • 14
  • should I add the c++ tag? – Darwin57721 Nov 10 '14 at 03:12
  • 2
    Only if you're working in C++ and will accept answers that only work in C++. – ApproachingDarknessFish Nov 10 '14 at 03:13
  • It sounds like the assignment is for you to figure this out, not ask about it on the internet. – fvgs Nov 10 '14 at 03:14
  • Yeah, that would be ok but I would prefer an answer that works in C and maybe if possible another way to do it in C++ but I don't want to ask to separate questions in the same post thats why I wasn't sure to add the c++ tag, I guess I will. – Darwin57721 Nov 10 '14 at 03:15
  • `char input[length + 1] = {0};`. – someuser Nov 10 '14 at 03:15
  • He basically wants to know if you can read the size of the input buffer BEFORE you read the data in the buffer, so you can create an appropriately sized array to read it into. – Clint Powell Nov 10 '14 at 03:17
  • @Wolfram I already 'solved' it (and got the problem accepted) I am just asking if there is a better way to do it. – Darwin57721 Nov 10 '14 at 03:17
  • @someuser I am not sure I understand. You are saying I missed to allocate space for the null terminator? – Darwin57721 Nov 10 '14 at 03:19
  • possible duplicate of [Correct way to read a text file into a buffer in C?](http://stackoverflow.com/questions/2029103/correct-way-to-read-a-text-file-into-a-buffer-in-c) – 2501 Nov 10 '14 at 03:20
  • There is an excess of similar questions, just pick one and mark as duplicate. – 2501 Nov 10 '14 at 03:21
  • @2501 It might be a duplicate but I think it isn't exactly the same question should I remove it? So, should I read the string character by character? – Darwin57721 Nov 10 '14 at 03:22
  • @2501 How do I mark it as duplicate? (I am somewhat new in here). Should I mark it as duplicate or it needs to be someone else. – Darwin57721 Nov 10 '14 at 03:27
  • @someuser So I missed by 1 the correct size but I need to explicitly put the null terminator? or is it ok just to do `char input[length+1]` and then just copy the string as it is above. – Darwin57721 Nov 10 '14 at 03:29
  • @Darwin57721, You need initialize a target string: `char input[length + 1] = {0};` || use `sprintf`: `sprintf(input, "%s", Mstring)` || put a null terminator after copying: `input[length + 1] = '\0'`. Three variants. – someuser Nov 10 '14 at 04:01
  • Thanks! I'll do it with the first one. – Darwin57721 Nov 10 '14 at 04:07
  • You dynamically allocate in C with malloc, but in this problem you never need to... you can read 1 at a time comparing to the first char until matched, then 2nd,3rd...last or till your read function returns 0. For optimization, you could do the same by reading fixed chunks at at time (I tend to use a `char buf[PAGE_SIZE];`) till read returns – technosaurus Nov 10 '14 at 04:22

1 Answers1

1

If you have the option of using C++ (as you mentioned), that is going to make your life a lot easier. You can then use a STL string (std::string) which manages dynamically sized strings for you. You can also drop the old scanf() beast and use std::cin.

Example:

#include <iostream>
#include <string>

void main()
{
    std::string sInput;
    std::getline(std::cin, sInput);

    // alternatively, you could execute this line instead:
    // std::cin >> sInput;
    // but that will tokenize input based on whitespace, so you
    // will only get one word at a time rather than an entire line
}

Describing how to manage strings that can grow dynamically in C will take considerably more explanation and care, and it sounds like you really don't need that. If so, however, here is a starting point: http://www.strchr.com/dynamic_arrays.

Nicholas Smith
  • 975
  • 7
  • 18
  • Thanks! Yeah, its ok in C++ but it would also be nice to know how to do it in C, I'll check the link. Checking if the array needs to be bigger wouldn't decrease performance? Do you know how `std::string` does it? – Darwin57721 Nov 10 '14 at 03:47
  • 1
    In short, a class like std::string would allocate an array of some default size X using malloc(X) in the constructor. When it needs to expand to hold more content, it uses realloc(Y) to expand the size of the allocated space and preserve the original content. It can also shrink its space using realloc(Z) if it deems necessary. – Nicholas Smith Nov 10 '14 at 17:21