2012-08-05 22 views
2

下面怪異的輸出是我的功能,它假設列出一些國家 我嘗試使用< <固定的,但似乎並不幫助C++用的printf

這是我的輸出:

�ѿra 
�ѿd Arab Emirates 
�ѿnistan 
�ѿua and Barbuda 
�ѿlla 
�ѿia 
�ѿia 
�ѿrlands Antilles 
�ѿa 
�ѿctica 
�ѿtina 
�ѿcan Samoa 

我文本文件是好的,我不知道我的數據轉換有錯誤。

這是我CountryData.cpp文件

#include <iostream> 
#include <string.h> 
#include "CountryData.h" 

using namespace std; 
// ==================================================================== 

void readData() 
{ 
    FILE * pFile; 
    NoOfRecordsRead = 0; 
    char buffer [Line_Char_Buffer_Size]; 

    pFile = fopen (INPUT_FILE_NAME , "r"); 

    if (pFile == NULL) 
     perror ("Error opening file 'Countries.txt' !"); 
    else 
    { 
     while (!feof (pFile)) 
     { 
      char* aLine = get_line (buffer, Line_Char_Buffer_Size, pFile); 

      if (aLine != NULL) 
      { 
//    printf ("%d] aLine => %s\n", NoOfRecordsRead, aLine); 
       globalCountryDataArray [NoOfRecordsRead++] = createCountryRecord (aLine); 
      } 
     } 

    fclose (pFile); 

    } 
} 

// ==================================================================== 

char* get_line (char *s, size_t n, FILE *f) 
{ 
    char *p = fgets (s, n, f); 

    if (p != NULL) 
    { 
     size_t last = strlen (s) - 1; 
     if (s[last] == '\n') 
      s[last] = '\0'; 
    } 
    return p; 
} 

// ==================================================================== 

CountryRecordType createCountryRecord (char* aLine) 
{ 
    CountryRecordType ctryRec; 
    char* pch = strtok (aLine, LINE_DATA_DELIMITER); 

    // 1) Retrieve TLD 
    strcpy (ctryRec.TLD, pch); 
    pch = strtok (NULL, LINE_DATA_DELIMITER); 

    // 2) Retrieve Country 
    strcpy (ctryRec.Country, pch); 
    pch = strtok (NULL, LINE_DATA_DELIMITER); 

    // 3) Retrieve FIPS104 
    strcpy (ctryRec.FIPS104, pch); 
    pch = strtok (NULL, LINE_DATA_DELIMITER); 

    // 4) Retrieve ISO2 
    strcpy (ctryRec.ISO2, pch); 
    pch = strtok (NULL, LINE_DATA_DELIMITER); 

    // 5) Retrieve ISO3 
    strcpy (ctryRec.ISO3, pch); 
    pch = strtok (NULL, LINE_DATA_DELIMITER); 

    // 6) Retrieve ISONo 
    ctryRec.ISONo = atof (pch); 
    pch = strtok (NULL, LINE_DATA_DELIMITER); 

    // 7) Retrieve Capital 
    strcpy (ctryRec.Capital, pch); 
    pch = strtok (NULL, LINE_DATA_DELIMITER); 

    // 8) Retrieve Region 
    strcpy (ctryRec.Region, pch); 
    pch = strtok (NULL, LINE_DATA_DELIMITER); 

    // 9) Retrieve Currency 
    strcpy (ctryRec.Currency, pch); 
    pch = strtok (NULL, LINE_DATA_DELIMITER); 

    // 10) Retrieve CurrencyCode 
    strcpy (ctryRec.CurrencyCode, pch); 
    pch = strtok (NULL, LINE_DATA_DELIMITER); 

    // 11) Retrieve Population 
    ctryRec.Population = atof (pch); 

    return (ctryRec); 

} 

// ==================================================================== 

char* displayRecordContent (CountryRecordType ctryRec) 
{ 
    char * output = ctryRec.Country; 
    return output; 

} 

// ==================================================================== 

void showAllRecords() 
{ 
    int i=0; 
    string stroutput; 
    char * result; 
    for (i=0; i<NoOfRecordsRead; i++) 
    { 

     result = displayRecordContent (globalCountryDataArray [i]); 
     stroutput += result; 
     stroutput += "\n"; 
    } 

cout << fixed << stroutput << endl; 

} 

// ==================================================================== 

int findCountryRecord (const char* countryName) 
{ 
    int idx  = -1; 
    int found = 0; 

    while (!found && (++idx < Max_Record_Size)) 
     if (strcmp (globalCountryDataArray [idx].Country, countryName) == 0) 
      found = 1; 

    if (found) 
     return (idx); 
    else 
     return (-1); 
} 

// ==================================================================== 

char* getCapital (const char* countryName) 
{ 
    int idx = findCountryRecord (countryName); 

    if (idx < 0) 
    { 
     printf ("Country '%s' not found!\n", countryName); 
     return (NULL); 
    } 
    else 
     return (globalCountryDataArray [idx].Capital); 
} 

// ==================================================================== 

char* getCurrencyCode (const char* countryName) 
{ 
    int idx = findCountryRecord (countryName); 

    if (idx < 0) 
    { 
     printf ("Country '%s' not found!\n", countryName); 
     return (NULL); 
    } 
    else 
     return (globalCountryDataArray [idx].CurrencyCode); 
} 


// ==================================================================== 

main() 
{ 
    readData(); 
    showAllRecords(); 


} 

這是我CountryData.h文件

#ifndef COUNTRY_DATA_H 
#define COUNTRY_DATA_H 

// ==================================================================== 

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

using namespace std; 
// ==================================================================== 

#define TLD_LEN    2 
#define COUNTRY_LEN   100 
#define FIPS104_LEN   2 
#define ISO2_LEN   2 
#define ISO3_LEN   3 
#define CAPITAL_LEN   100 
#define REGION_LEN   100 
#define CURRENCY_LEN  50 
#define CURRENCY_CODE_LEN 3 

#define No_Of_Rec_Fields  11 
#define Max_Record_Size   250 
#define Line_Char_Buffer_Size 400 

#define LINE_DATA_DELIMITER  "," 
#define INPUT_FILE_NAME   "Countries.txt" 

// ==================================================================== 

//const char* LINE_DATA_DELIMITER  = ","; 
//const char* INPUT_FILE_NAME   = "Countries.txt"; 


typedef struct CountryRecord 
{ 
    char TLD   [TLD_LEN+1];   // Top Level Domain code 
    char Country  [COUNTRY_LEN+1];  
    char FIPS104  [FIPS104_LEN+1];  // Ctry code according to FIPS104 standard 
    char ISO2   [ISO2_LEN+1];   // Ctry code according to ISO2 standard 
    char ISO3   [ISO3_LEN+1];   // Ctry code according to ISO3 standard 
    double ISONo; 

    char Capital  [CAPITAL_LEN+1];  
    char Region   [REGION_LEN+1];   // E.g. Asia, Europe, etc. 
    char Currency  [CURRENCY_LEN+1];  // Full name of currency 
    char CurrencyCode [CURRENCY_CODE_LEN+1]; // Currency abbreviation 
    double Population; 

} CountryRecordType; 

int NoOfRecordsRead; 
CountryRecordType globalCountryDataArray [Max_Record_Size]; 

// ==================================================================== 

void readData(); 
char* get_line (char *s, size_t n, FILE *f); 
CountryRecordType createCountryRecord (char* aLine); 
char* displayRecordContent (CountryRecordType ctryRec); 
void showAllRecords(); 

int findCountryRecord (const char* countryName); 
char* getCapital (const char* countryName); 
char* getCurrencyCode (const char* countryName); 

// ==================================================================== 

#endif // COUNTRY_DATA_H 

這是我countries.txt文件

AD,Andorra,AN,AD,AND,20.00,Andorra la Vella,Europe,Euro,EUR,67627.00 
AE,United Arab Emirates,AE,AE,ARE,784.00,Abu Dhabi,Middle East,UAE Dirham,AED,2407460.00 
AF,Afghanistan,AF,AF,AFG,4.00,Kabul,Asia,Afghani,AFA,26813057.00 
AG,Antigua and Barbuda,AC,AG,ATG,28.00,Saint John's,Central America and the Caribbean,East Caribbean Dollar,XCD,66970.00 
AI,Anguilla,AV,AI,AIA,660.00,The Valley,Central America and the Caribbean,East Caribbean Dollar,XCD,12132.00 
AL,Albania,AL,AL,ALB,8.00,Tirana,Europe,Lek,ALL,3510484.00 
AM,Armenia,AM,AM,ARM,51.00,Yerevan,Commonwealth of Independent States,Armenian Dram,AMD,3336100.00 
AN,Netherlands Antilles,NT,AN,ANT,530.00,Willemstad,Central America and the Caribbean,Netherlands Antillean guilder,ANG,212226.00 
AO,Angola,AO,AO,AGO,24.00,Luanda,Africa,Kwanza,AOA,10366031.00 
AQ,Antarctica,AY,AQ,ATA,10.00,--,Antarctic Region, , ,0.00 
AR,Argentina,AR,AR,ARG,32.00,Buenos Aires,South America,Argentine Peso,ARS,37384816.00 
AS,American Samoa,AQ,AS,ASM,16.00,Pago Pago,Oceania,US Dollar,USD,67084.00 
AT,Austria,AU,AT,AUT,40.00,Vienna,Europe,Euro,EUR,8150835.00 
AU,Australia,AS,AU,AUS,36.00,Canberra,Oceania,Australian dollar,AUD,19357594.00 
+0

「我的文本文件是好的」 - 什麼是編碼?你如何讀取數據? – 2012-08-05 16:19:19

+1

什麼是'CountryRecordType',它的'Country'是如何分配的? – juanchopanza 2012-08-05 16:20:23

+2

國際海事組織,你需要從決定你是否真的想寫C或C++開始,然後做到這一點。現在,你正試圖將兩者結合起來,但大多數都是以混亂的方式結束(IMO)。 – 2012-08-05 16:29:02

回答

4

的一部分,因爲你正在通過CountryRecordTypedisplayRecordContent,您返回的指針是無效的,並使用它會導致未定義的行爲。這是因爲您正在返回一個指向由函數調用期間創建的副本所保存的內容的指針,該指針在函數返回時被破壞。

修改您的displayRecordContent函數以使用通過引用代替。

const char* displayRecordContent (const CountryRecordType &ctryRec) 
{ 
    const char * output = ctryRec.Country; 
    return output; 

} 
0

我從地上爬起來重寫代碼相當多,試圖實際上C++的混合在幾個位使用C++而不是C的。

#include <vector> 
#include <string> 
#include <iostream> 
#include <iterator> 
#include <fstream> 

struct CountryRecord { 
    std::string TLD; 
    std::string Country; 
    std::string FIPS104; 
    std::string ISO2; 
    std::string ISO3; 
    double ISONo; 
    std::string Capital; 
    std::string Region; 
    std::string Currency; 
    std::string CurrencyCode; 
    double Population; 
}; 

template <class T> 
std::istream &get_field(std::istream &is, T &field) { 
    is >> field; 
    is.ignore(1); 
    return is; 
} 

template<> 
std::istream &get_field<std::string>(std::istream &is, std::string &field) { 
    return std::getline(is, field, ','); 
} 

std::istream &operator>>(std::istream &is, CountryRecord &r) { 
    get_field(is, r.TLD); 
    get_field(is, r.Country); 
    get_field(is, r.FIPS104); 
    get_field(is, r.ISO2); 
    get_field(is, r.ISO3); 
    get_field(is, r.ISONo); 
    get_field(is, r.Capital); 
    get_field(is, r.Region); 
    get_field(is, r.Currency); 
    get_field(is, r.CurrencyCode); 
    return get_field(is, r.Population); 
} 

std::ostream &operator<<(std::ostream &os, CountryRecord const &r) { 
    return os << r.Country; 
} 

int main() { 
    std::ifstream in("countries.txt"); 
    std::vector<CountryRecord> countries(
     (std::istream_iterator<CountryRecord>(in)), 
     std::istream_iterator<CountryRecord>()); 

    std::copy(countries.begin(), countries.end(), 
       std::ostream_iterator<CountryRecord>(std::cout, "\n")); 

    return 0; 
}