-1

I have a program that is supposed to take an unknown number of strings from a user. It supposed to check and see if a string has already been entered so that there will be no duplicates in the dynamic array.

The problem is that I can't get the program to recognize when an array slot has nothing in it. I've used both NULL and nullptr and neither works. What's more is even though I haven't fully initialized the array, there's still something in the location.

#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "new"

int _tmain(int argc, _TCHAR* argv[])
{
    //Variables
    int i=0,end=0,requiresSize=1;
    char ** temp;
    char  item[256]="a";
    char ** requires;

    //Requires is initialized as an array, but the individiual slots are not
    requires = new char * [requiresSize];


    while(strcmp(item,"q-")){
        end=0;
        printf("Enter h- for help.\nEnter q- to quit.\n");
        printf("Please enter a string\n");
        gets_s(item);
        printf("%s\n",item);
        if(!strcmp(item,"h-")){
            printf("Enter a string to add to the list.\nEnter p- to print the list.\n");
            end=1;
        }   
        if(!strcmp(item,"q-")){
            break;
        }
        if(!strcmp(item,"p-")){
            if(requires[0]!=nullptr){
                for(int j=0;j<requiresSize;j++){
                    printf("%d. %s\n",j,&requires[j]);
                }
            }
            end=1;
        }
        while(end==0){
            //if search index is larger than size of the array,reallocate the array
            if(i>= requiresSize){
                temp = new char * [requiresSize*2];
                //Initialize each element in temp
                for(int j=0;j<requiresSize*2;j++){
                    temp[j]= new char[256];
                }
                for(int j =0;j<requiresSize;j++){
                    //for each element in requires, copy that element to temp
                    strncpy_s(temp[j],_TRUNCATE,requires[j],_TRUNCATE);
                }
                delete *requires;
                requires = temp;
                requiresSize = requiresSize *2;         
            }
            //if the index at requires is not empty, check to see if it is the same as given item
            if(requires[i]!= nullptr){//This should be returning false and preventing the nested if from running, but doesn't
                if(!strcmp( item,  requires[i])){//runtime error occurs here from trying to access requires[i]
                    //if they are the same, break out of the loop, item is already included
                    break;
                }else{
                    //otherwise, increase the index and check again (continue loop)
                    i++;
                    break;
                }
            }else{
                //if the index is empty, add the item to the list and break out of loop
                requires[i]= new char [256];
                strncpy_s(requires[i],_TRUNCATE,item,_TRUNCATE);
                break;
            }

        }
    }
    delete *temp;
    delete requires;
    return 0;
}

I can't figure out what I'm missing or put in the wrong place

Chaospyke
  • 62
  • 9
  • Which book are you reading? The reason I ask is that people who read books seem to write better code than this. You're using way too many C functions, when there are more appropriate C++ alternatives, and **some of your code invokes undefined behaviour** (e.g. `char ** temp;` ... `delete *temp;` as there is no requirement that `temp` contain anything sane, `requires = new char * [requiresSize];` ... `delete requires;` and similarly `requires[i]= new char [256];` ... `delete *requires;` use `delete` erroneously where `delete[]` should be used)... – autistic May 02 '17 at 04:26

2 Answers2

2
requires = new char * [requiresSize];

This creates a new array of pointer-to-char using default initialization. Default-initializing an array causes default-initialization of its elements. For non-class and non-array types (such as pointers), default initialization does nothing. The value of each element is therefore unspecified, and not necessarily equal to nullptr.

This is why your if conditional doesn't always succeed. It's not that it's failing to match nullptr values, it's that some of the values you are testing are not equal to nullptr because nothing ever set them to nullptr in the first place.

otherwise, nothing is done: the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values.

You can perform value initialization by adding () after the dimension. Value-initializing an array causes value-initialization of each array element. For non-class and non-array types, value-initialization has the same effect as assignment of zero, which will initialize the contents of each element to nullptr for an array of pointers:

requires = new char * [requiresSize]();

otherwise, the object is zero-initialized.

However, there is no reason to be futzing about with pointer arrays here. Use a standard library container like std::vector<std::string>.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
0

Looking at the contents of something that isn't initialized is bad because you don't know what's in it. So the fact that your array has stuff in it even though you haven't initialized it isn't a problem, the problem is you trying to access that stuff.

Always initialize your variables to a default value after you create them, then work with them.

Second, may I suggest you use std::string and std::vector? With std::vector you can:

myVector.push_back("Whatever");
myVector.at(0); // this will return an out of reach exception if it doesn't exist

std::vector will grow as you use it and you can iterate through all members after with

for (int i = 0; i < myVector.size(); i++)
{
// Do stuff myVector.at(i);
}
Pedro
  • 74
  • 1
  • 11