You are on page 1of 8

Bài 1:

Hãy viết hàm int findSpan(const char s1[], int start, const char s2[]) để tìm từ vị trí start trong
chuỗi s1, vị trí đầu tiên xuất hiện bất kỳ ký tự nào của chuỗi s2.
- Trường hợp start < 0, hàm bắt đầu tìm từ đầu chuỗi.
- Trường hợp không tìm thấy hoặc start vượt quá chuỗi s1, hàm trả về độ dài chuỗi s1 (vị trí
kết thúc chuỗi '\0').
Yêu cầu:
- Có thể phát sinh các hàm phụ để hỗ trợ.
- Không dùng std::string hoặc các hàm trong thư viện <string.h>.
Ví dụ:
findSpan("the@quick#fox", 0, "@#") trả về 3.
findSpan("the@quick#fox", 5, "@#") trả về 9.
findSpan("the@quick#fox", 0, "!&") trả về 13.

int len(const char s[]){


int len = 0;
while(s[len++] != '\0');
return len - 1;
}

int findSpan(const char s1[], int start, const char s2[]){


if (start < 0) start = 0;
int len1 = 0, len2 = 0;
while (s1[len1++] != '\0');
while (s2[len2++] != '\0');
len1 = len1 - 1;
len2 = len2 - 1;
for (int i = start; i < len1 ;i++){
for (int j = 0; j < len2; j++){
if (s1[i] == s2[j]) return i;
}
}
return len1;
}
Bài 2:
Hãy viết hàm int countSpan(const char s1[], int start, const char s2[]) để đếm từ vị trí start
trong chuỗi s1, độ dài vùng chỉ chứa các ký tự của chuỗi s2.
- Trường hợp start < 0, hàm bắt đầu đếm từ đầu chuỗi.
- Trường hợp start vượt quá chuỗi s1, hàm trả về 0.
Yêu cầu:
- Có thể phát sinh các hàm phụ để hỗ trợ.
- Không dùng std::string hoặc các hàm trong thư viện <string.h>.
Ví dụ:  

countSpan("the!@quick#&&fox",  3, "@#!&") trả về 2.


countSpan("the!@quick#&&fox",  6, "@#!&") trả về 0.
countSpan("the!@quick#&&fox", 12, "@#!&") trả về 1.

int len(const char s[]){


int len = 0;
while(s[len++] != '\0');
return len - 1;
}

int countSpan(const char s1[], int start, const char s2[]){


int len1 = len(s1), len2 = len(s2), count = 0;
if (start < 0) start = 0;
bool flag = true;
for (int i = start; i < len1 && flag; i++){
for (int j = 0; j < len2; j++){
if (s1[i] == s2[j]){
count++;
break;
}
if (j == len2 - 1) flag = false;
}
}
return count;
}
Bài 3:
Cho kiểu cấu trúc phân số:
typedef struct {
     int numerator, denominator;
} Fraction;
Hãy viết hàm Fraction parseFraction(const char s[]) để chuyển đổi chuỗi s thành phân số,
chuỗi s có một trong bốn định dạng "numerator/denominator", hoặc "numerator", hoặc
"/denominator" hoặc "/".
Yêu cầu:
- Có thể phát sinh các hàm phụ để hỗ trợ.
- Có thể sử dụng hàm atoi trong thư viện <stdlib.h> để đổi chuỗi thành số.
- Có thể sử dụng hàm strcpy và strncpy trong thư viện <string.h> để sao chép chuỗi con.
- Không sử dụng std::string hoặc các hàm khác trong thư viện <string.h>.
Ví dụ:
parseFraction("18/23") trả về phân số 18/23
parseFraction("1823")  trả về phân số 1823/1
parseFraction("/23")   trả về phân số 1/23
parseFraction("/") trả về phân số 1/1
Cách sao chép chuỗi con bằng strcpy và strncpy:
char s[] = "the quick fox"; // Chuỗi nguồn
char u[10];
char v[10];

// Sao chép chuỗi con "quick" từ s vào u.


// - Sao chép s, bắt đầu từ vị trí 4, lấy 5 ký tự.
// - Thêm ký tự kết thúc chuỗi.
strncpy( u, s + 4, 5 );
u[5] = '\0';

// Sao chép chuỗi con "fox" từ s vào v.


// - Sao chép s, bắt đầu từ vị trí 10, đến hết chuỗi (sao chép luôn ký tự kết thúc chuỗi).
// - Không cần thêm ký tự kết thúc chuỗi.
strcpy( v, s + 10 );
typedef struct {
int numerator, denominator;
} Fraction;
int len(const char s[]){
int i = 0;
while(s[i++] != '\0');
return i - 1;
}
int find(const char s[]){
int i = 0;
for (; i < len(s); i++){
if (s[i] == '/') break;
}
return i;
}

Fraction parseFraction(const char s[]){


int size = len(s);
Fraction phanSo;
if (s[0] == '/' && s[1] == '\0') {
phanSo.numerator = 1;
phanSo.denominator = 1;
} else if (s[0] == '/'){
char so[size] ;
strcpy(so,s + 1);
phanSo.numerator = 1;
phanSo.denominator = atoi(so);
} else if (find(s) == size){
phanSo.numerator = atoi(s);
phanSo.denominator = 1;
} else {
char tu[size], mau[size];
int index = find(s);
strncpy(tu, s, index);
tu[index] = '\0';
strcpy(mau, s + index + 1);
phanSo.numerator = atoi(tu);
phanSo.denominator = atoi(mau);
}
return phanSo;
}
Bài 4:
Viết chương trình C/C++ thực hiện các việc sau:
(tổ chức thành nhiều hàm và chia làm nhiều tập tin mã nguồn)
            - Nhập vào từ bàn phím một chuỗi chứa các phân số xen lẫn với các ký tự khác.
            - Trích và xuất ra màn hình ra danh sách các phân số từ chuỗi vừa nhập.
     Định dạng nhập:
          xyz2/4@#&!12@ab/6
     Định dạng xuất:
          2/4 12/1 1/6
Ràng buộc:
- Tổ chức chương trình theo nhiều hàm và chia làm nhiều tập tin mã nguồn.
- Sử dụng lại các hàm và kiểu cấu trúc ở câu 1, 2, 3 cho chương trình.
- Có thể phát sinh các hàm phụ để hỗ trợ.
- Có thể sử dụng hàm atoi trong thư viện <stdlib.h> để đổi chuỗi thành số.
- Có thể sử dụng các hàm strcpy và strncpy trong thư viện <string.h> để sao chép chuỗi
con.
- Không sử dụng std::string hoặc các hàm khác trong thư viện <string.h>.

#include <iostream>
#include <string.h>
#include <stdlib.h>
#define MAX 100

using namespace std;

typedef struct {
int numerator, denominator;
} Fraction;

int len(const char s[]){


int len = 0;
while(s[len++] != '\0');
return len - 1;
}
int find(const char s[]){
int i = 0;
for (; i < len(s); i++){
if (s[i] == '/') break;
}
return i;
}
Fraction parseFraction(const char s[]){
int size = len(s);
Fraction phanSo;
if (s[0] == '/' && s[1] == '\0') {
phanSo.numerator = 1;
phanSo.denominator = 1;
} else if (s[0] == '/'){
char so[size] ;
strcpy(so,s + 1);
phanSo.numerator = 1;
phanSo.denominator = atoi(so);
} else if (find(s) == size){
phanSo.numerator = atoi(s);
phanSo.denominator = 1;
} else {
char tu[size], mau[size];
int index = find(s);
strncpy(tu, s, index);
tu[index] = '\0';
strcpy(mau, s + index + 1);
phanSo.numerator = atoi(tu);
phanSo.denominator = atoi(mau);
}
return phanSo;
}
int countSpan(const char s1[], int start, const char s2[]){
int len1 = len(s1), len2 = len(s2), count = 0;
if (start < 0) start = 0;
bool flag = true;
for (int i = start; i < len1 && flag; i++){
for (int j = 0; j < len2; j++){
if (s1[i] == s2[j]){
count++;
break;
}
if (j == len2 - 1) flag = false;
}
}
return count;
}
int findSpan(const char s1[], int start, const char s2[]){
if (start < 0) start = 0;
int len1 = 0, len2 = 0;
while (s1[len1++] != '\0');
while (s2[len2++] != '\0');
len1 = len1 - 1;
len2 = len2 - 1;
for (int i = start; i < len1 ;i++){
for (int j = 0; j < len2; j++){
if (s1[i] == s2[j]) return i;
}
}
return len1;
}
void splitAndParse(const char s[], char num[][MAX], Fraction phanSo[]){
int size = len(s);
char numList[] = "1234567890/";
int index = findSpan(s, 0, numList);

// So luong phan so
int count = 0, sizeOfFrac;
while(index != size){
sizeOfFrac = countSpan(s, index, numList);
strncpy(num[count], s + index, sizeOfFrac);
num[count++][sizeOfFrac] = '\0';
index = findSpan(s, index + sizeOfFrac, numList);
}
for (int i = 0; i < count; i++){
phanSo[i] = parseFraction(num[i]);
}
}
int main(){
char s[MAX] = "xyz2/4@#&!12@ab/6";
char num[MAX][MAX];
Fraction phanSo[MAX];
splitAndParse(s, num, phanSo);
for (int i = 0; i < 3; i++){
cout << phanSo[i].numerator << " " << phanSo[i].denominator << endl;
}
}

You might also like