2013-09-05 2 views
3

Я пытаюсь организовать свой код, группируя функции в отдельных файлах заголовка/источника. Я # включил заголовочный файл в моем основном .cpp, но компилятор не видит функции в convertTypes.cpp. Что дает? И как я использую свой «ключ» 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; 
} 

convertTypes.h

#ifdef CONVERTTYPES_H 
#define CONVERTTYPES_H 

std::string convertToNoteName(int, int); 

key convertKeyStringToKeyStruct(std::string); 

#endif 

convertTypes.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; 
} 
+1

Вам нужно определить все типы, прежде чем вы используете их, поэтому вам нужно объявить структуру 'key' в convertTypes.h, если вы хотите, чтобы ваши функции возвращали ее. – PeterT

+1

Не извиняйтесь за много кода - сделайте так, чтобы не было много кода. Divide and conquer - это решающее умение отладки, и вы можете также изучить его сейчас. –

+0

Помимо '# ifdef', вы должны' #include 'в' convertTypes.h'. – juanchopanza

ответ

4

Изменение:

#ifdef CONVERTTYPES_H 

к:

#ifndef CONVERTTYPES_H 

Вы эффективно составляете свои определения.

Что касается второго пункта, двигаться в этом:

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

в файл заголовка (перед первым использованием там).

Однако я бы предостерег от использования имени, такого как key, поскольку оно обычно используется как имя переменной. Я бы пошел за key_t или MySpecialKeyForStuffImDoing (или что-то вроде этого).

+0

А, спасибо. Noob error :) – staxas

+0

Кстати, существует ли распространенная практика для определения глобальных типов, перечислений и т. Д. В отдельных файлах для крупных проектов? Скажем, я хотел использовать структуру «key» в нескольких файлах .h/.cpp, хочу ли я создать для этого отдельную конструкцию? – staxas

+0

@staxas Да, это обычное дело. Создайте файл под названием 'Types.h' или' MyTypes.h' и включите их в любой ** заголовочный файл **, который их использует. – trojanfoe

3

В дополнение к @ trojanfor-х Anwer: также создать новый NoteMaker.h, содержащий определение key структуры или переместить определение stuct в convertTypes.h так, что вы не дублировать его в нескольких местах

+0

Я переместил typedef в NoteMaker.h, но convertTypes больше не распознает «ключ». Мне нужен #include «NoteMaker.h» в моем convertTypes.h? – staxas

+0

да, определенно !! –

Смежные вопросы