01/10/2018, 09:59

Vector và con trỏ

Mình có viết một hàm GetTokens() chỉ lấy 1 hoặc 2 tokens bằng C. Bây giờ mình muốn đổi sang C++ và sử dụng vector để lưu giá trị 2 tokens đó. Mình muốn hàm GetTokens() trả về một con trỏ tới vector nhưng mình không chắc lắm. Mấy bạn có cho mình ý kiến với.

Đây là header của mình:

#ifndef Tokenizer_h
#define Tokenizer_h
#include <vector>
using namespace std;

class Tokenizer {
    public: 
    is_number(char *arr);
    vector<string>* GetTokens(); 

};
#endif

Còn đây là hàm GetTokens

#include <vector>
#include <stdlib.h>
#include <strings.h>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <string>

#include "Tokenizer.hpp"

using namespace std;

int is_number(char *arr){
    int check = 0;
    for (int i= 0; i < strlen(arr); i++){
        if (isdigit(arr[i])){
                //check = 0; //number
        } else check++;//string
            //*arr++;
    }
    if (check == 0)
        return 0;//number
    else
        return 1; //string
}

vector<string>* GetTokens()
{
    vector<string> *ptrVT = new vector<string>();;
    int countVT = 0;
    char str[256];
    char *ptr;
    char *ptr2;
    char **b = (char **)malloc(256*sizeof(char));
    char *p;
    int count =0;
    int index;
    int j =0;
    int num_space;
    int checkNumCL = 0;
    do{

            do{
                count = 0;
                index = 0;
                num_space = 0;
                countVT =0;
                /*if (checkNumCL > numCL)
                {
                    exit(0);
                }*/

                //stdin_flush();
                cout << "> " ;
                fgets(str,66,stdin);
                str[strlen(str)-1] = '';
                if (strlen(str)>20){
                    cout << "ERROR! Input string too long." << endl;
                    //checkNumCL++ ;
                    continue;
                }
                ptr = str;
                while (*ptr != ''){
                    if (*ptr == ' '){
                        num_space++;
                    }
                    ptr++;
                }
                p = strtok(str," ");
                while (p != NULL){
                    b[index] = p;
                    ptrVT->push_back(&p[index]);
                    count++;
                    index++;
                    countVT++;
                    p = strtok(NULL," ");
                }
                if (count > 2 || count <= 0){
                    cout << "ERROR! Incorrect number of tokens found." << endl;
                    //checkNumCL++ ;
                }
                
                ptr = str;
            }while(count > 2 || count <= 0);



        if (count == 2){
            char temp[256] = {};
            for (int i=0; i < count; i++){
                if (is_number(b[i]) == 0)//number
                    strcat(temp,"INT");
                else
                    strcat(temp,"STR");
            }
            if (strcasecmp(temp,"STRINT")!= 0){
                cout << "ERROR! Expected STR INT." << endl;
                //checkNumCL++ ;
                continue;
            }
        }

        else if(count == 1)
        {
            if(is_number(b[0]) == 0){
                cout << "ERROR! Expected STR." << endl;
                //checkNumCL++ ;
                continue;

            }
        }

        if (strcasecmp(str,"quit") == 0){
            exit(0);
        }


        j = 0;
        while (j < index){
            if (is_number(b[j]) == 0)
                cout << "INT ";
            else
                cout << "STR ";
            j++;
        }
        checkNumCL++;
        
        printf("
");
    }while(strcasecmp(str,"quit
") != 0); //&& checkNumCL < numCL);
    return ptrVT;
}


Trần Hoàn viết 12:14 ngày 01/10/2018

Trong class thì bạn khai báo vector<string>* GetTokens(); Trong định nghĩa hàm thì lại là vector<string> GetTokens(int numCL). Rốt cuộc bạn muốn trả về con trỏ hay trả về vector?
Với cả nếu trả về con trỏ hay vector, tại sao lại return 0?

Huy Nguyen viết 12:15 ngày 01/10/2018

Mình bỏ nhầm code cũ. Mình đã update lại rồi đó bạn. Bạn xem giúp mình là mình đã khai báo biến trong header va class đã đúng chưa. Thầy mình yêu cầu là file Tokenizer.cpp sẽ trả về con trỏ của vector kiểu string.

Đây là lỗi lúc mình compile. Không biết có phải là mình dùng C code trong C++ sẽ bị lỗi không?

Compiling: g++ Instructor_prog2_2.cpp Tokenizer.cpp -o proginstructor_2_2
In file included from Instructor_prog2_2.cpp:8:0:
Tokenizer.hpp:16:24: error: ISO C++ forbids declaration of 'is_number' with no type [-fpermissive]
     is_number(char *arr);
                        ^
In file included from Tokenizer.cpp:1:0:
Tokenizer.hpp:16:24: error: ISO C++ forbids declaration of 'is_number' with no type [-fpermissive]
     is_number(char *arr);
                        ^
Tokenizer.cpp:5:31: error: ISO C++ forbids declaration of 'is_number' with no type [-fpermissive]
 Tokenizer::is_number(char *arr){
                               ^
Tokenizer.cpp: In function 'std::vector >* Tokenizer()':
Tokenizer.cpp:64:48: error: no matching function for call to 'std::vector >::push_back(char&)'
                     VTname.push_back(p[countVT]);
                                                ^
In file included from /usr/include/c++/6/vector:64:0,
                 from Tokenizer.hpp:3,
                 from Tokenizer.cpp:1:
/usr/include/c++/6/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::__cxx11::basic_string; _Alloc = std::allocator >; std::vector<_Tp, _Alloc>::value_type = std::__cxx11::basic_string]
       push_back(const value_type& __x)
       ^~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:914:7: note:   no known conversion for argument 1 from 'char' to 'const value_type& {aka const std::__cxx11::basic_string&}'
/usr/include/c++/6/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::__cxx11::basic_string; _Alloc = std::allocator >; std::vector<_Tp, _Alloc>::value_type = std::__cxx11::basic_string]
       push_back(value_type&& __x)
       ^~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:932:7: note:   no known conversion for argument 1 from 'char' to 'std::vector >::value_type&& {aka std::__cxx11::basic_string&&}'
Tokenizer.cpp:83:35: error: 'is_number' was not declared in this scope
                 if (is_number(b[i]) == 0)//number
                                   ^
Tokenizer.cpp:97:30: error: 'is_number' was not declared in this scope
             if(is_number(b[0]) == 0){
                              ^
Tokenizer.cpp:112:31: error: 'is_number' was not declared in this scope
             if (is_number(b[j]) == 0)
                               ^
Tokenizer.cpp:122:5: error: expected ';' before 'return'
     return VTname;
     ^~~~~~
Tokenizer.cpp:122:12: error: cannot convert 'std::vector >' to 'std::vector >*' in return
     return VTname;
            ^~~~~~
Compile Fail
Trần Hoàn viết 12:15 ngày 01/10/2018

phương thức is_number() chưa có kiểu dữ liệu.
trong phương thức GetTokens(), bạn sai cú pháp. Đọc kỹ thông báo lỗi đi :))

Huy Nguyen viết 12:08 ngày 01/10/2018

Hàm is_number mình đã khai báo biến con trỏ như vậy không được hả bạn. Còn trong hàm GetTokens mình muốn lấy giá trị lấy từ con trỏ đẩy vào vector có được không vậy bạn. Vì trong chương trình mình viết bằng C, mình dùng hàm strtok để lấy giá và dùng hàm con trỏ để chỉ tới giá trị cần lấy. Từ C chuyển qua C++ nên mình không rành lắm

Trần Hoàn viết 12:12 ngày 01/10/2018

Gợi ý dài dòng quá. Mình chỉ luôn lỗi nhé:
Hàm is_number, bạn khai báo thế này:

public: 
    is_number(char *arr);

Thế thì rốt cuộc hàm này trả về cái gì? Nếu không trả về gì thì phải là void is_number(char* arr); chứ

Thứ 2:
Hàm GetTokens(); được khai báo ở trên, ở dưới lại có hàm Tokenizer() nào thế?

Thứ 3:

do
{...
}while(strcasecmp(str,"quit\n") != 0) //&& checkNumCL < numCL);
    return VTname;

Thế dấu ; trước return đâu?

Thứ 4:
Hàm Tokenizer() trả về kiểu dữ liệu vector<string>* trong khi VTname là kiểu dữ liệu vector<string>, làm sao mà return được.

Huy Nguyen viết 12:14 ngày 01/10/2018

Cảm ơn bạn. Mình đã fix những lỗi nhỏ đó nhưng vẫn không chạy được. Mình đã updated code của mình. Bạn xem giúp mình là mình dùng push_back(p[index]) để gán giá trị từ token vào trong vector có đúng không?

Đây là lỗi của mình

Compiling: g++ Instructor_prog2_2.cpp Tokenizer.cpp -o proginstructor_2_2
/tmp/ccsoBxBn.o: In function `main':
Instructor_prog2_2.cpp:(.text+0x12a): undefined reference to `Tokenizer::GetTokens[abi:cxx11]()'
collect2: error: ld returned 1 exit status
Compile Fail
Dark.Hades viết 12:00 ngày 01/10/2018

undefined reference to `Tokenizer

Hàm này đã được khai báo đâu, bạn phải đọc log để debug chứ.

Huy Nguyen viết 12:05 ngày 01/10/2018

Mình đã include header vào trong Tokenizer.cpp rồi mà tại sao mình vẫn phải dùng :: để vào hàm GetTokens là sao bạn? Bạn có thể giải thích cho mình được không?

Trần Hoàn viết 12:01 ngày 01/10/2018

đúng, vẫn phải dùng vector<string>* Tokenizer::GetTokens() để định nghĩa.

Dark.Hades viết 12:14 ngày 01/10/2018

Như bạn viết:

vector<string>* GetTokens()
{
// ...
}

Nó chỉ là 1 hàm ở bên ngoài chương trình, không liên quan gì tới class cả

Huy Nguyen viết 12:12 ngày 01/10/2018

Vậy làm cách nào để định nghĩa nó trong header vậy bạn?

Trần Hoàn viết 12:12 ngày 01/10/2018

Bạn đưa vào header như thế là đúng rồi. Nhưng chỉ có tác dụng cho chương trình biết được Tokenizer thôi. Còn muốn xây dựng hàm thì vẫn phải dùng toán tử ::

Huy Nguyen viết 12:15 ngày 01/10/2018
Compiling: g++ Instructor_prog2_2.cpp Tokenizer.cpp -o proginstructor_2_2
Tokenizer.cpp:29:12: error: 'vector' in 'class Tokenizer' does not name a template type
 Tokenizer::vector* GetTokens()

Mình có thể trả về con trỏ của vector được không bạn?

Trần Hoàn viết 12:11 ngày 01/10/2018

bạn thực sự không biết về toán tử :: à. Thấy cú pháp mình đưa ở trên không?

Bài liên quan
0