C ++ strings without <string> and STL

I haven’t used C ++ much in the past, and lately I've been working a lot with C #, and I'm really struggling to get back to the basics of C ++ again. This is especially difficult, since the work indicates that you cannot use any of the most convenient C ++ constructs, so all strings must be * characters, and no provision is made for STL lists.

What I'm trying to do now is to create a list of strings that won’t take me time to use STL or C #. Basically I want to have a function like:

char **registeredNames = new char*[numberOfNames]; 

Then,

 RegisterName(const * char const name, const int length) { //loop to see if name already registered snipped if(notFound) { registeredNames[lastIndex++] = name; } } 

or if it was C # ...

 if(!registeredNames.Contains(name)) { registeredNames.Add(name); } 

and I understand that this does not work. I know that the constant nature of the variables passed (constant pointer and constant string) makes this quite difficult, but my main problem is that I always avoided this situation in the past using STL lists, etc., so I never had to work around this is!

+4
source share
14 answers

You will probably need to use strcmp to find out if the string is saved:

 for (int index=0; index<=lastIndex; index++) { if (strcmp(registeredNames[index], name) == 0) { return; // Already registered } } 

Then, if you really need to keep a copy of the string, you will need to allocate a buffer and copy the characters.

 char* nameCopy = malloc(length+1); strcpy(nameCopy, name); registeredNames[lastIndex++] = nameCopy; 

You did not indicate whether your NULL entry is complete - if not, you need additional help, and strcmp / strcpy is not suitable.

+5
source

There are legitimate reasons why STL can be avoided. When working in fixed environments where memory or speed is paramount, it is sometimes difficult to say what happens under the hood with STL. Yes, you can write your own memory allocators, and yes, speed is usually not a problem, but there are differences between STL implementations on different platforms, and these differences can be subtle and potentially erroneous. Memory is perhaps the biggest problem when I think about using it.

Memory is precious, and the way we use it requires tight control. If you have not taken this path, this concept may not make sense, but it is true. We allow the use of STL in tools (outside the game code), but this is prohibited inside the game itself. Another issue is code size. I'm a little unsure how much STL can contribute to the size of the executable, but we have seen a noticeable increase in code size when using STL. Even if your executable is “only” 2M larger, it is 2M less RAM for something else for your game.

STL is certainly good. But this can be abused by programmers who do not know what they are doing. This is not intentional, but can bring unpleasant surprises when you do not want to see them (again, memory overflow and performance problems)

I am sure that you are close with your decision.

 for ( i = 0; i < lastIndex; i++ ) { if ( !strcmp(&registeredNames[i], name ) { break; // name was found } } if ( i == lastIndex ) { // name was not found in the registeredNames list registeredNames[lastIndex++] = strdup(name); } 

You might not want to use strdup. This is just an example of how to store a name based on your example. You might want to make sure that you either don’t want to allocate space for the new name yourself, or use some other memory design that may already be available in your application.

And please don't write a string class. I looked at string classes as perhaps the worst example of how not to reverse-engineer the underlying C construct in C ++. Yes, the string class can hide a lot of nifty details from you, but the memory usage patterns are terrible, and they fit poorly into the console environment (e.g. ps3 or 360, etc.). About 8 years ago we did the same. 200000+ memory allocation before we get to the main menu. The memory was terribly fragmented, and we could not get the rest of the game to fit into a fixed environment. We are done with this.

Class design is great for some things, but it's not one of them. This is an opinion, but it is based on the experience of the real world.

+6
source

If portability is a problem, you can check STLport .

+5
source

Why can't you use STL?

In any case, I suggest you implement a simple string class and your own list templates. Thus, you can use the same methods as you, and only support pointers and memory management in these classes. If you imitate the STL, it will be even better.

+3
source

If you really can't use stl (and I'm sorry that this is true when I was in the gaming industry), can you create your own class of strings? The simplest of the string classes will allocate memory for construction and assignment and handle deletion in the destructor. Later you could add additional features as needed. Fully portable and very easy to write and unit test.

+2
source

Edit: I think I misunderstood your question. There is no problem with the constant in this code that I know of.

I am doing this from my head, but this should be correct:

 static int lastIndex = 0; static char **registeredNames = new char*[numberOfNames]; void RegisterName(const * char const name) { bool found = false; //loop to see if name already registered snipped for (int i = 0; i < lastIndex; i++) { if (strcmp(name, registeredNames[i] == 0)) { found = true; break; } } if (!found) { registeredNames[lastIndex++] = name; } } 
+1
source

Working with char * requires working with C functions. In your case, you need to copy the lines. To help you, you have the strndup function. Then you have to write something like:

 void RegisterName(const char* name) { // loop to see if name already registered snipped if(notFound) { registerNames[lastIndex++] = stdndup(name, MAX_STRING_LENGTH); } } 

This code suppose your array is big enough.

Of course, it would be best to correctly implement your own string, array, and list ... or convince your boss that STL is no longer evil!

+1
source

Using:

 const char **registeredNames = new const char * [numberOfNames]; 

will allow you to assign const * char const to an array element.

Just out of curiosity, why does "work require that none of the most convenient C ++ constructs be used"?

+1
source

I can understand why you cannot use STL - most of them inflate your code a lot. However, there are implementations for game programmers by game programmers - RDESTL is one such library.

+1
source

If you're not worried about agreements and just want to get the job done, use realloc. I do such things for lists all the time, it happens something like this:

 T** list = 0; unsigned int length = 0; T* AddItem(T Item) { list = realloc(list, sizeof(T)*(length+1)); if(!list) return 0; list[length] = new T(Item); ++length; return list[length]; } void CleanupList() { for(unsigned int i = 0; i < length; ++i) { delete item[i]; } free(list) } 

You can do more, for example. only realloc every time the size of the list is doubled, functions to remove items from the list by index or by checking equality, creating a template class to process lists, etc. (I have one that I wrote many years ago and always use myself ... but, unfortunately, I'm at work and can't just copy it here). To be completely honest, this probably will not exceed the STL equivalent, although it can be compared to its performance if you are doing a ton of work or doing STLs especially poorly.

Annoyingly C ++ does not update / modify the operator to replace realloc, which would be very useful.

Oh, and apologies if my code is wrong, I just pulled it out of memory.

0
source

All the proposed approaches are valid, my point is that the way C # is attractive, replicates it, creates its own classes / interfaces to represent the same abstraction, i.e. a simple linked list class with Contains and Add methods using a code sample provided by other answers should be relatively simple.

One of the great features of C ++ is that, as a rule, you can make it look and act the way you want if the other language has a great implementation of what you can usually reproduce.

0
source

Conjugate correctness is still correct, regardless of whether you use STL or not. I believe that you are looking to register const char ** a const char ** so that the registeredNames[i] assignment (which is const char * ) is executed.

Also, is this really what you want to do? It seems like a copy of the string is probably more appropriate.

In addition, you should not think about keeping this in the list, given the operation you perform on it, but it will be better.

0
source

I have used this String class for many years.

http://www.robertnz.net/string.htm

It provides almost all STL functions, but is implemented as a true class, not a template, and does not use STL.

0
source

This is a clear case where you can collapse yourself. And do the same for the vector class.

  • Do this with test programming.
  • Keep it simple.

Avoid references to line buffer counting if you are in an MT environment.

0
source

Source: https://habr.com/ru/post/1276858/


All Articles