簡體   English   中英

C ++奇怪的輸出與printf

[英]C++ weird output with 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

這是我的country.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

由於您CountryRecordType值將displayRecordContent傳遞給displayRecordContent ,因此返回的指針無效,並且使用它會導致未定義的行為。 這是因為您將返回一個指向函數調用過程中所復制內容的內容的指針,該副本在函數返回時會被破壞。

修改displayRecordContent函數以改為使用按引用傳遞。

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

}

我將徹底重寫代碼,嘗試實際上使用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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM