3

我试图通过在单独的头文件/源文件中分组函数来组织我的代码。我已经在我的主 .cpp 中#included 头文件,但编译器看不到 convertTypes.cpp 中的函数。是什么赋予了?以及如何在全局范围内使用我的'key' typedef(在单独的函数源中也是如此)?代码很多,不好意思。

/*
 * NoteMaker.cpp
 *
 *  Created on: Sep 4, 2013
 *      Author: edwinrietmeijer
 */


typedef struct {
    int keyNum;
    int keyType;
} key;

#include <iostream>
#include <string>
#include <iomanip>
#include "convertTypes.h"

using namespace std;

const int KEYSET[ ] = { 0, 2, 4, 5, 7, 8, 9 };

int* generateNotes( int, key );
void echoNoteList( const int* , const int, const key );
string getKeyStringFromUser();

int main() {

    key keyStruct;
    int octave;
    int nrOfNotes;
    string firstNoteName;

    // Get inputs
    cout << "What key would you like to generate notes in? ( f, cis, es, etc.)" << endl;
    firstNoteName = getKeyStringFromUser();
    cout << "In what octave would you like to generate notes? (-1 / 9)" << endl;
    cin >> octave;
    octave += 1;
    cout << "How many notes do you wish to generate?" << endl;
    cin >> nrOfNotes;

    // create a key data struct from input string
    keyStruct = convertKeyStringToKeyStruct( firstNoteName );

    // add the starting octave nr to the keyStruct
    keyStruct.keyNum += octave * 12;

    // generate note list
    int* noteList = new int[ nrOfNotes ];
    noteList = generateNotes( nrOfNotes, keyStruct );

    // echo note list to terminal
    echoNoteList( noteList , nrOfNotes, keyStruct);
    cin.get();
}

int* generateNotes( int notes, key keyStruct) {
    int* newList = new int [notes];
    int currNote = keyStruct.keyNum + keyStruct.keyType;
    int currDist = 0;
    newList[0] = currNote;

    for (int i=1; i < notes; i ++) {
        currDist = i % 7;
        if ( currDist == 0 || currDist == 3 ) // half step or whole step?
        { currNote = currNote + 1; }
        else
        { currNote = currNote + 2; }

        newList[ i ] = currNote;
    }
    cout << "Generated list." << endl;
    return newList;
}

void echoNoteList( const int* noteList, const int nrOfNotes, const key thisKeyStruct )
{
    int currNote;

    for (int i = 0; i < nrOfNotes ; i ++) {
        currNote = noteList[ i ]  % 12;
        if ( currNote < 0 )
            currNote += 12;
        cout << left;
        cout << setw(5) << noteList[ i ] << setw( 5 ) << convertToNoteName( currNote, thisKeyStruct.keyType ) << endl;
    }
}


string getKeyStringFromUser() {
    bool correctInput = false;
    string getKeyName;
    int keyNum;
    while ( ! correctInput ) {
        cin >> getKeyName;
        cout << endl;
        keyNum = getKeyName[ 0 ];
        if ( keyNum > 96 && keyNum < 104 ) {
            correctInput = true;
        }
        else
        {
            cout <<  "Wrong input. Try again." << endl;
        }
    }
    return getKeyName;
}

转换类型.h

#ifdef CONVERTTYPES_H
#define CONVERTTYPES_H

std::string convertToNoteName( int, int );

key convertKeyStringToKeyStruct( std::string );

#endif

转换类型.cpp

    /*
 * convertTypes.cpp
 *
 *  Created on: Sep 5, 2013
 *      Author: edwinrietmeijer
 */
#include <string>
#include "convertTypes.h"

using namespace std;

typedef struct {
    int keyNum;
    int keyType;
} key;

key convertKeyStringToKeyStruct( string firstNote ) {
    int stringSize;
    int keyType = 0;
    char keyChar;
    key thisKey;
    keyChar = firstNote[ 0 ];

    // get key type (flat, sharp, normal)
    stringSize = firstNote.size( );
    if (stringSize > 1 ) {
        switch( firstNote[ 1 ] ) {
        case 'e':
            keyType = -1; break;
        case 's':
            keyType = -1; break;
        case 'i':
            keyType = 1; break;
        default:
            keyType = 0; break;
        }
    }
    // convert key char to ascii code
    int ASkey = keyChar;
    thisKey.keyNum = KEYSET[ ASkey - 99 ];
    thisKey.keyType = keyType;
    return thisKey;
}


string convertToNoteName( int thisNote, int thisKeyType = 0) {

    string noteName;
    char addKeyType;

    switch( thisKeyType ) {
    case -1:
        addKeyType = 'b'; break;
    case 0:
        addKeyType =' '; break;
    case 1:
        addKeyType = '#'; break;
    }

        switch( thisNote ) {
        case 0:
            noteName = "C"; break;
        case 1:
            if( thisKeyType == 1)
                noteName = string ("C") + addKeyType;
            else
                noteName = string("D") + addKeyType; break;
        case 2:
            noteName = "D"; break;
        case 3:
            if( thisKeyType == 1)
                noteName = string ("D") + addKeyType;
            else
                noteName = string("E") + addKeyType; break;
        case 4:
            noteName = "E"; break;
        case 5:
            noteName = "F"; break;
        case 6:
            if( thisKeyType == 1)
                noteName = string ("F") + addKeyType;
            else
                noteName = string("G") + addKeyType; break;
        case 7:
            noteName = "G"; break;
        case 8:
            if( thisKeyType == 1)
                noteName = string ("G") + addKeyType;
            else
                noteName = string("A") + addKeyType; break;
        case 9:
            noteName = "A"; break;
        case 10:
            if( thisKeyType == 1)
                noteName = string ("A") + addKeyType;
            else
                noteName = string("B") + addKeyType; break;
        case 11:
            noteName = "B"; break;
        default:
            noteName = "!"; break;
        }
        return noteName;
}
4

2 回答 2

4

改变:

#ifdef CONVERTTYPES_H

至:

#ifndef CONVERTTYPES_H

您正在有效地编译您的定义。

至于你的第二点,移动这个:

typedef struct {
    int keyNum;
    int keyType;
} key;

进入头文件(在第一次使用之前)。

但是,我会警告不要使用key通常用作变量名的名称。我会选择key_tMySpecialKeyForStuffImDoing(或类似的)。

于 2013-09-05T12:03:38.400 回答
3

除了@trojanfor 的答案:还创建一个NoteMaker.h包含key结构定义的新文件或将结构定义移动到,convertTypes.h这样您就不会在多个地方复制它

于 2013-09-05T12:07:52.467 回答