Thread: use of the STL with map

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    50

    use of the STL with map

    I am experiencing some unexpected behavior when trying to use map to store some filenames given a directory. My code looks like this:

    Code:
    typedef map<string, char*> MapType;
    
    
    int getFilesFromDir(char* directory, MapType &files) {
            DIR *dp;
            struct dirent *dirp;
            regex_t re;
    
            if ((dp = opendir(directory)) == NULL) {
                    cout << "Error(" << errno << ") opening input directory: " << directory << endl;
                    return errno;
            }
    
    
            while ( (dirp=readdir(dp))!=NULL ) {
                    if ( regcomp(&re, "^IM[-][[:digit:]]{4}[-][[:digit:]]{4}[.][Pp][Nn][Mm]$", REG_EXTENDED|REG_NOSUB)!=0 )
                            continue;
                    else {
                            int status = regexec(&re, dirp->d_name, (size_t)0, NULL, 0);
    
                            regfree(&re);
    
                            if (status != 0) {
                                    cout << "regex condition not satisfied......" << dirp->d_name << endl;
                                    continue;
                            } else {
                                    string key;
                                    key = dirp->d_name[8];
                                    key += dirp->d_name[9];
                                    key += dirp->d_name[10];
                                    key += dirp->d_name[11];
                                    key += '\0';
                                    //files[key] = (char*)(dirp->d_name);
                                    files.insert(std::pair<string, char*>(key, (char*)dirp->d_name));
                                    cout << key << ": " << files[key] << endl;
    
                                    key = '0';
                                    key += '0';
                                    key += '0';
                                    key += '1';
                                    key += '\0';
                                    cout << key << ": " << files[key] << endl;
                            }
                    }
            }
    
            char buffer [4];
            for (unsigned int i=1; i<= files.size(); i++) {
                    string key;
                    sprintf(buffer, "%.4i", i);
                    key = buffer;
                    key += '\0';
    
                    cout << key << ": " << files[key] << endl;
            }
    
            closedir(dp);
            return 0;
    }
    The directory I am passing has 361 converted (to pnm) dicom files with a naming format IM-####-####.pnm. I've added some cout statements to understand why my 0001 key is changing values from IM-0001-0001.pnm to 0103.pnm after file IM-0001-0101.pnm is inserted into the files map container.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > files.insert(std::pair<string, char*>(key, (char*)dirp->d_name));
    The pointer returned by readdir points to a fixed area in memory used to return ALL the file names, one at a time.
    This just makes ALL your map entries point a the same char array.

    Make a COPY of d_name in a std::string, then use that to create your map.

    > char buffer [4];
    I suggest you look up stringstreams as well.
    This (or rather your later use of it) results in another buffer overflow.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2010
    Posts
    50
    I have implemented the suggestions in the following code block, however I am still getting the same result:

    Code:
    int getFilesFromDir(char* directory, MapType &files) {
            DIR *dp;
            struct dirent *dirp;
            regex_t re;
    
            if ((dp = opendir(directory)) == NULL) {
                    cout << "Error(" << errno << ") opening input directory: " << directory << endl;
                    return errno;
            }
    
    
            while ( (dirp=readdir(dp))!=NULL ) {
                    if ( regcomp(&re, "^IM[-][[:digit:]]{4}[-][[:digit:]]{4}[.][Pp][Nn][Mm]$", REG_EXTENDED|REG_NOSUB)!=0 )
                            continue;
                    else {
                            char* filename = dirp->d_name;
                            int status = regexec(&re, filename, (size_t)0, NULL, 0);
    
                            regfree(&re);
    
                            if (status != 0) {
                                    cout << "regex condition not satisfied......" << filename << endl;
                                    continue;
                            } else {
                                    string key;
                                    stringstream ss (stringstream::in | stringstream::out);
                                    int start_index = 8;
                                    int end_index = 11;
                                    char key_char;
    
                                    for (int f_index=start_index; f_index<=end_index; f_index++)
                                            ss << filename[f_index];
    
                                    for (int f_index=start_index; f_index<=end_index; f_index++) {
                                            ss >> key_char;
                                            key += key_char;
                                    }
                                    key += '\0';
    
                                    //files[key] = (char*)(filename);
                                    files.insert(std::pair<string, char*>(key, (char*)filename));
                                    cout << key << ": " << files[key] << endl;
                                    key = '0';
                                    key += '0';
                                    key += '0';
                                    key += '1';
                                    key += '\0';
                                    cout << key << ": " << files[key] << endl;
                            }
                    }
            }
    
            char buffer [4];
            for (unsigned int i=1; i<= files.size(); i++) {
                    string key;
                    sprintf(buffer, "%.4i", i);
                    key = buffer;
                    key += '\0';
    
                    cout << key << ": " << files[key] << endl;
            }
    
            closedir(dp);
            return 0;
    }

    Any ideas?

  4. #4
    Registered User
    Join Date
    Feb 2010
    Posts
    50
    forgot to mention, i had to make a copy of d_name in a char*, as that is what the regexec f(n) is going to expect.

  5. #5
    Registered User
    Join Date
    Feb 2010
    Posts
    50
    In case it helps, the result of that final loop is:

    0001 : 0307.pnm
    0002 : 0308.pnm
    0003 : 0309.pnm
    0004 : 0310.pnm
    0005 : 0311.pnm
    0006 : 0312.pnm
    0007 : 0313.pnm
    0008 : 0314.pnm
    0009 : 0315.pnm
    0010 : 0316.pnm
    0011 : 0317.pnm
    0012 : 0318.pnm
    0013 : 0319.pnm
    0014 : 0320.pnm
    0015 : 0321.pnm
    0016 : 0322.pnm
    0017 : 0323.pnm
    0018 : 0324.pnm
    0019 : 0325.pnm
    0020 : 0326.pnm
    0021 : 0327.pnm
    0022 : 0328.pnm
    0023 : 0329.pnm
    0024 : 0330.pnm
    0025 : 0331.pnm
    0026 : 0332.pnm
    0027 : 0333.pnm
    0028 : 0334.pnm
    0029 : 0335.pnm
    0030 : 0336.pnm
    0031 : 0337.pnm
    0032 : 0338.pnm
    0033 : 0339.pnm
    0034 : 0340.pnm
    0035 : 0341.pnm
    0036 : 0342.pnm
    0037 : 0343.pnm
    0038 : 0344.pnm
    0039 : 0345.pnm
    0040 : 0346.pnm
    0041 : 0347.pnm
    0042 : 0348.pnm
    0043 : 0349.pnm
    0044 : 0350.pnm
    0045 : 0351.pnm
    0046 : 0352.pnm
    0047 : 0353.pnm
    0048 : 0354.pnm
    0049 : 0355.pnm
    0050 : 0356.pnm
    0051 : 0357.pnm
    0052 : 0358.pnm
    0053 : 0359.pnm
    0054 : 0360.pnm
    0055 : 0361.pnm
    0056 : 0001-gpu.pnm
    0057 : 0261.pnm
    0058 : 0262.pnm
    0059 : 0263.pnm
    0060 : 0264.pnm
    0061 : 0265.pnm
    0062 : 0266.pnm
    0063 : 0267.pnm
    0064 : 0268.pnm
    0065 : 0269.pnm
    0066 : 0270.pnm
    0067 : 0271.pnm
    0068 : 0272.pnm
    0069 : 0273.pnm
    0070 : 0274.pnm
    0071 : 0275.pnm
    0072 : 0276.pnm
    0073 : 0277.pnm
    0074 : 0278.pnm
    0075 : 0279.pnm
    0076 : 0280.pnm
    0077 : 0281.pnm
    0078 : 0282.pnm
    0079 : 0283.pnm
    0080 : 0284.pnm
    0081 : 0285.pnm
    0082 : 0286.pnm
    0083 : 0287.pnm
    0084 : 0288.pnm
    0085 : 0289.pnm
    0086 : 0290.pnm
    0087 : 0291.pnm
    0088 : 0292.pnm
    0089 : 0293.pnm
    0090 : 0294.pnm
    0091 : 0295.pnm
    0092 : 0296.pnm
    0093 : 0297.pnm
    0094 : 0298.pnm
    0095 : 0299.pnm
    0096 : 0300.pnm
    0097 : 0301.pnm
    0098 : 0302.pnm
    0099 : 0303.pnm
    0100 : 0304.pnm
    0101 : IM-0001-0305.pnm
    0102 : IM-0001-0306.pnm
    0103 : IM-0001-0307.pnm
    0104 : IM-0001-0308.pnm
    0105 : IM-0001-0309.pnm
    0106 : IM-0001-0310.pnm
    0107 : IM-0001-0311.pnm
    0108 : IM-0001-0312.pnm
    0109 : IM-0001-0313.pnm
    0110 : IM-0001-0314.pnm
    0111 : IM-0001-0315.pnm
    0112 : IM-0001-0316.pnm
    0113 : IM-0001-0317.pnm
    0114 : IM-0001-0318.pnm
    0115 : IM-0001-0319.pnm
    0116 : IM-0001-0320.pnm
    0117 : IM-0001-0321.pnm
    0118 : IM-0001-0322.pnm
    0119 : IM-0001-0323.pnm
    0120 : IM-0001-0324.pnm
    0121 : IM-0001-0325.pnm
    0122 : IM-0001-0326.pnm
    0123 : IM-0001-0327.pnm
    0124 : IM-0001-0328.pnm
    0125 : IM-0001-0329.pnm
    0126 : IM-0001-0330.pnm
    0127 : IM-0001-0331.pnm
    0128 : IM-0001-0332.pnm
    0129 : IM-0001-0333.pnm
    0130 : IM-0001-0334.pnm
    0131 : IM-0001-0335.pnm
    0132 : IM-0001-0336.pnm
    0133 : IM-0001-0337.pnm
    0134 : IM-0001-0338.pnm
    0135 : IM-0001-0339.pnm
    0136 : IM-0001-0340.pnm
    0137 : IM-0001-0341.pnm
    0138 : IM-0001-0342.pnm
    0139 : IM-0001-0343.pnm
    0140 : IM-0001-0344.pnm
    0141 : IM-0001-0345.pnm
    0142 : IM-0001-0346.pnm
    0143 : IM-0001-0347.pnm
    0144 : IM-0001-0348.pnm
    0145 : IM-0001-0349.pnm
    0146 : IM-0001-0350.pnm
    0147 : IM-0001-0351.pnm
    0148 : IM-0001-0352.pnm
    0149 : IM-0001-0353.pnm
    0150 : IM-0001-0354.pnm
    0151 : IM-0001-0355.pnm
    0152 : IM-0001-0356.pnm
    0153 : IM-0001-0357.pnm
    0154 : IM-0001-0358.pnm
    0155 : IM-0001-0359.pnm
    0156 : IM-0001-0360.pnm
    0157 : IM-0001-0361.pnm
    0158 : IM-0001-0001-gpu.pnm
    0159 : IM-0001-0261.pnm
    0160 : IM-0001-0262.pnm
    0161 : IM-0001-0263.pnm
    0162 : IM-0001-0264.pnm
    0163 : IM-0001-0265.pnm
    0164 : IM-0001-0266.pnm
    0165 : IM-0001-0267.pnm
    0166 : IM-0001-0268.pnm
    0167 : IM-0001-0269.pnm
    0168 : IM-0001-0270.pnm
    0169 : IM-0001-0271.pnm
    0170 : IM-0001-0272.pnm
    0171 : IM-0001-0273.pnm
    0172 : IM-0001-0274.pnm
    0173 : IM-0001-0275.pnm
    0174 : IM-0001-0276.pnm
    0175 : IM-0001-0277.pnm
    0176 : IM-0001-0278.pnm
    0177 : IM-0001-0279.pnm
    0178 : IM-0001-0280.pnm
    0179 : IM-0001-0281.pnm
    0180 : IM-0001-0282.pnm
    0181 : IM-0001-0283.pnm
    0182 : IM-0001-0284.pnm
    0183 : IM-0001-0285.pnm
    0184 : IM-0001-0286.pnm
    0185 : IM-0001-0287.pnm
    0186 : IM-0001-0288.pnm
    0187 : IM-0001-0289.pnm
    0188 : IM-0001-0290.pnm
    0189 : IM-0001-0291.pnm
    0190 : IM-0001-0292.pnm
    0191 : IM-0001-0293.pnm
    0192 : IM-0001-0294.pnm
    0193 : IM-0001-0295.pnm
    0194 : IM-0001-0296.pnm
    0195 : IM-0001-0297.pnm
    0196 : IM-0001-0298.pnm
    0197 : IM-0001-0299.pnm
    0198 : IM-0001-0300.pnm
    0199 : IM-0001-0301.pnm
    0200 : IM-0001-0302.pnm
    0201 : IM-0001-0303.pnm
    0202 : IM-0001-0304.pnm
    0203 : IM-0001-0305.pnm
    0204 : IM-0001-0306.pnm
    0205 : IM-0001-0307.pnm
    0206 : IM-0001-0308.pnm
    0207 : IM-0001-0309.pnm
    0208 : IM-0001-0310.pnm
    0209 : IM-0001-0311.pnm
    0210 : IM-0001-0312.pnm
    0211 : IM-0001-0313.pnm
    0212 : IM-0001-0314.pnm
    0213 : IM-0001-0315.pnm
    0214 : IM-0001-0316.pnm
    0215 : IM-0001-0317.pnm
    0216 : IM-0001-0318.pnm
    0217 : IM-0001-0319.pnm
    0218 : IM-0001-0320.pnm
    0219 : IM-0001-0321.pnm
    0220 : IM-0001-0322.pnm
    0221 : IM-0001-0323.pnm
    0222 : IM-0001-0324.pnm
    0223 : IM-0001-0325.pnm
    0224 : IM-0001-0326.pnm
    0225 : IM-0001-0327.pnm
    0226 : IM-0001-0328.pnm
    0227 : IM-0001-0329.pnm
    0228 : IM-0001-0330.pnm
    0229 : IM-0001-0331.pnm
    0230 : IM-0001-0332.pnm
    0231 : IM-0001-0333.pnm
    0232 : IM-0001-0334.pnm
    0233 : IM-0001-0335.pnm
    0234 : IM-0001-0336.pnm
    0235 : IM-0001-0337.pnm
    0236 : IM-0001-0338.pnm
    0237 : IM-0001-0339.pnm
    0238 : IM-0001-0340.pnm
    0239 : IM-0001-0341.pnm
    0240 : IM-0001-0342.pnm
    0241 : IM-0001-0343.pnm
    0242 : IM-0001-0344.pnm
    0243 : IM-0001-0345.pnm
    0244 : IM-0001-0346.pnm
    0245 : IM-0001-0347.pnm
    0246 : IM-0001-0348.pnm
    0247 : IM-0001-0349.pnm
    0248 : IM-0001-0350.pnm
    0249 : IM-0001-0351.pnm
    0250 : IM-0001-0352.pnm
    0251 : IM-0001-0353.pnm
    0252 : IM-0001-0354.pnm
    0253 : IM-0001-0355.pnm
    0254 : IM-0001-0356.pnm
    0255 : IM-0001-0357.pnm
    0256 : IM-0001-0358.pnm
    0257 : IM-0001-0359.pnm
    0258 : IM-0001-0360.pnm
    0259 : IM-0001-0361.pnm
    0260 : IM-0001-0001-gpu.pnm
    0261 : IM-0001-0261.pnm
    0262 : IM-0001-0262.pnm
    0263 : IM-0001-0263.pnm
    0264 : IM-0001-0264.pnm
    0265 : IM-0001-0265.pnm
    0266 : IM-0001-0266.pnm
    0267 : IM-0001-0267.pnm
    0268 : IM-0001-0268.pnm
    0269 : IM-0001-0269.pnm
    0270 : IM-0001-0270.pnm
    0271 : IM-0001-0271.pnm
    0272 : IM-0001-0272.pnm
    0273 : IM-0001-0273.pnm
    0274 : IM-0001-0274.pnm
    0275 : IM-0001-0275.pnm
    0276 : IM-0001-0276.pnm
    0277 : IM-0001-0277.pnm
    0278 : IM-0001-0278.pnm
    0279 : IM-0001-0279.pnm
    0280 : IM-0001-0280.pnm
    0281 : IM-0001-0281.pnm
    0282 : IM-0001-0282.pnm
    0283 : IM-0001-0283.pnm
    0284 : IM-0001-0284.pnm
    0285 : IM-0001-0285.pnm
    0286 : IM-0001-0286.pnm
    0287 : IM-0001-0287.pnm
    0288 : IM-0001-0288.pnm
    0289 : IM-0001-0289.pnm
    0290 : IM-0001-0290.pnm
    0291 : IM-0001-0291.pnm
    0292 : IM-0001-0292.pnm
    0293 : IM-0001-0293.pnm
    0294 : IM-0001-0294.pnm
    0295 : IM-0001-0295.pnm
    0296 : IM-0001-0296.pnm
    0297 : IM-0001-0297.pnm
    0298 : IM-0001-0298.pnm
    0299 : IM-0001-0299.pnm
    0300 : IM-0001-0300.pnm
    0301 : IM-0001-0301.pnm
    0302 : IM-0001-0302.pnm
    0303 : IM-0001-0303.pnm
    0304 : IM-0001-0304.pnm
    0305 : IM-0001-0305.pnm
    0306 : IM-0001-0306.pnm
    0307 : IM-0001-0307.pnm
    0308 : IM-0001-0308.pnm
    0309 : IM-0001-0309.pnm
    0310 : IM-0001-0310.pnm
    0311 : IM-0001-0311.pnm
    0312 : IM-0001-0312.pnm
    0313 : IM-0001-0313.pnm
    0314 : IM-0001-0314.pnm
    0315 : IM-0001-0315.pnm
    0316 : IM-0001-0316.pnm
    0317 : IM-0001-0317.pnm
    0318 : IM-0001-0318.pnm
    0319 : IM-0001-0319.pnm
    0320 : IM-0001-0320.pnm
    0321 : IM-0001-0321.pnm
    0322 : IM-0001-0322.pnm
    0323 : IM-0001-0323.pnm
    0324 : IM-0001-0324.pnm
    0325 : IM-0001-0325.pnm
    0326 : IM-0001-0326.pnm
    0327 : IM-0001-0327.pnm
    0328 : IM-0001-0328.pnm
    0329 : IM-0001-0329.pnm
    0330 : IM-0001-0330.pnm
    0331 : IM-0001-0331.pnm
    0332 : IM-0001-0332.pnm
    0333 : IM-0001-0333.pnm
    0334 : IM-0001-0334.pnm
    0335 : IM-0001-0335.pnm
    0336 : IM-0001-0336.pnm
    0337 : IM-0001-0337.pnm
    0338 : IM-0001-0338.pnm
    0339 : IM-0001-0339.pnm
    0340 : IM-0001-0340.pnm
    0341 : IM-0001-0341.pnm
    0342 : IM-0001-0342.pnm
    0343 : IM-0001-0343.pnm
    0344 : IM-0001-0344.pnm
    0345 : IM-0001-0345.pnm
    0346 : IM-0001-0346.pnm
    0347 : IM-0001-0347.pnm
    0348 : IM-0001-0348.pnm
    0349 : IM-0001-0349.pnm
    0350 : IM-0001-0350.pnm
    0351 : IM-0001-0351.pnm
    0352 : IM-0001-0352.pnm
    0353 : IM-0001-0353.pnm
    0354 : IM-0001-0354.pnm
    0355 : IM-0001-0355.pnm
    0356 : IM-0001-0356.pnm
    0357 : IM-0001-0357.pnm
    0358 : IM-0001-0358.pnm
    0359 : IM-0001-0359.pnm
    0360 : IM-0001-0360.pnm
    0361 : IM-0001-0361.pnm

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Did you read anything?

    > Make a COPY of d_name in a std::string, then use that to create your map.
    char *filename = dirp->d_name;
    isn't any better than what you had already.

    std::string filename = dirp->d_name;
    is a whole new ball game.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Feb 2010
    Posts
    50
    how would you suggest to convert filename to conform with the regexec functions aforementioned second parameter type (const char *) to avoid a compile-time type error?

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Have you studied all the methods offered by std::string?

    Code:
    int status = regexec(&re, filename.c_str(), (size_t)0, NULL, 0);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Feb 2010
    Posts
    50
    I used that (not in the code above, but since my last post), but am still getting the same issue. I've noticed that if i use a map of string key, string value, then the problem goes away. I'll proceed with this. However, I am still curious how the char* type as a map value was not allowing me to properly map these directory entries. Btw, thanks for the coding tips!

  10. #10
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    A map of string to string is exactly what others have indirectly been trying to tell you to use.
    You were previously mapping from a string to a char pointer and as has been said, the char pointer is the same each time even though it containts a different string each time around. Do you not understand pointers yet?
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  11. #11
    Registered User
    Join Date
    Feb 2010
    Posts
    50
    A map of string to string is exactly what others have indirectly been trying to tell you to use.
    Correct. I simply mentioned the use of a string to string map to more directly present a workaround and close the thread.

    You were previously mapping from a string to a char pointer and as has been said, the char pointer is the same each time even though it containts a different string each time around. Do you not understand pointers yet?
    I understand that dirp is the same each time, and that d_name, the different string you refer to, is in fact different each time. What I was hoping somebody would bring to light is why the initial (among others) element's value in the map container was changing when it did not seem to be referenced in the loop (btw, initial was probably not a proper term to use...instead think the map element whose key is '0001'). If somebody could post with this explanation I would find quite a bit of value in that. Thanks!
    Last edited by nicoeschpiko; 04-29-2011 at 10:58 AM.

Popular pages Recent additions subscribe to a feed