From 78b175beece53efbe0477a8280017c73e7b83815 Mon Sep 17 00:00:00 2001 From: Gorsky Kirill Date: Wed, 13 Mar 2024 05:56:53 +0300 Subject: [PATCH 1/2] dupfind: code duplication finder --- dupfind/Makefile | 17 ++++ dupfind/dupfind | Bin 0 -> 105728 bytes dupfind/main.cpp | 182 ++++++++++++++++++++++++++++++++++++ dupfind/result.txt | 225 +++++++++++++++++++++++++++++++++++++++++++++ dupfind/sample.sh | 5 + 5 files changed, 429 insertions(+) create mode 100644 dupfind/Makefile create mode 100755 dupfind/dupfind create mode 100644 dupfind/main.cpp create mode 100644 dupfind/result.txt create mode 100755 dupfind/sample.sh diff --git a/dupfind/Makefile b/dupfind/Makefile new file mode 100644 index 0000000..0903494 --- /dev/null +++ b/dupfind/Makefile @@ -0,0 +1,17 @@ +.PHONY: all install clean uninstall + +CC=g++ + +all: dupfind + +dupfind: main.cpp + $(CC) main.cpp -o dupfind + +clean: + rm -f dupfind + +install: dupfind + cp dupfind /usr/local/bin + +uninstall: + rm -f /usr/local/bin/dupfind diff --git a/dupfind/dupfind b/dupfind/dupfind new file mode 100755 index 0000000000000000000000000000000000000000..218846a5b965b33c38da291c6b211469e4d99d73 GIT binary patch literal 105728 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 literal 0 HcmV?d00001 diff --git a/dupfind/main.cpp b/dupfind/main.cpp new file mode 100644 index 0000000..76a108e --- /dev/null +++ b/dupfind/main.cpp @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define SEQ_SEARCH_DEPTH 3 +#define SEQ_REPORT_THRESHOLD 4 +#define SIMLARITY_THRESHOLD 0.7 + +struct LineData { + std::string str; + std::string tab; + size_t group_ind; +}; + +struct GroupData { + std::vector members; + const char *color; +}; + +std::vector lines; +std::string file_name; +std::unordered_map groups; + +struct { + bool show = false; +} cfg; + +// trim from end (in place) +inline void rtrim(std::string &s) +{ + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { + return !std::isspace(ch); + }).base(), s.end()); +} + +int strDistance(std::string &a, std::string &b) +{ + if (a.size() == 0) + return b.size(); + + if (b.size() == 0) + return a.size(); + + std::vector> dp(a.size(), std::vector(b.size())); + dp[0][0] = 0; + for (size_t i = 1; i < a.size(); i++) + dp[i][0] = i; + for (size_t j = 1; j < b.size(); j++) + dp[0][j] = j; + + for (size_t i = 1; i < a.size(); i++) { + for (size_t j = 1; j < b.size(); j++) { + dp[i][j] = std::min(std::min(dp[i][j - 1] + 1, dp[i - 1][j] + 1), dp[i - 1][j - 1] + (a[i] != b[j])); + } + } + + return dp.back().back(); +} + +void assignLineToGroup(int n, float threshold) +{ + bool ok = false; + for (int i = 0; i < n; i++) { + float similarity = 1.f - (float)strDistance(lines[n].str, lines[i].str) / (float)std::max(lines[n].str.size(), lines[i].str.size()); + + if (similarity >= threshold) { + groups[i].members.push_back(n); + lines[n].group_ind = i; + ok = true; + break; + } + } + + if (!ok) { + groups[n].members.push_back(n); + } +} + +void printLines(int first, int last) +{ + for (int i = first; i <= last; i++) { + std::cout << lines[i].tab << ' ' << lines[i].str << std::endl; + } +} + +void detectSeq(int len, int first, int last) +{ + if (len >= SEQ_REPORT_THRESHOLD) { + std::cout << file_name << ": [" << first+1 << ", " << last+1 << "] duplicates [" << + lines[first].group_ind+1 << ", " << lines[last].group_ind+1 << "]\n"; + + if (cfg.show) { + std::cout << "\n...\n"; + printLines(lines[first].group_ind, lines[last].group_ind); + std::cout << "...\n"; + printLines(first, last); + std::cout << "...\n"; + } + } +} + +void findDupSeqs() +{ + size_t seq_len = 1; + size_t seq_first = 0; + size_t seq_last = 0; + for (size_t i = 1; i < lines.size(); i++) { + if (i - seq_last > SEQ_SEARCH_DEPTH) { + detectSeq(seq_len, seq_first, seq_last); + seq_len = 1; + seq_last = i; + seq_first = i; + } + + int diff = lines[i].group_ind - lines[seq_last].group_ind; + if (diff == 1) { + seq_last = i; + seq_len++; + } + } + + detectSeq(seq_len, seq_first, seq_last); +} + +bool shouldAssign(int n) +{ + if (lines[n].str == "}" || lines[n].str == "{") + return false; + if (lines[n].str.size() > 0 && lines[n].str[0] == '#') + return false; + return true; +} + +int main(int argc, char **argv) +{ + if (argc < 2) { + std::cout << "Usage: code-dup FILENAMES...\n"; + exit(1); + } + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--show") == 0) { + cfg.show = true; + continue; + } + + lines.clear(); + groups.clear(); + + file_name = argv[i]; + std::ifstream file(argv[i]); + if (!file.is_open()) { + std::cout << "Failed to open file\n"; + exit(1); + } + + std::string line; + while (std::getline(file, line)) { + rtrim(line); + + size_t i = 0; + while (i < line.size() && isspace(line[i])) i++; + std::string tab = line.substr(0, i); + line = line.substr(i, line.size() - i); + + lines.push_back({ line, tab, 0 }); + } + file.close(); + + for (size_t j = 0; j < lines.size(); j++) { + if (shouldAssign(j)) + assignLineToGroup(j, SIMLARITY_THRESHOLD); + } + + findDupSeqs(); + } +} diff --git a/dupfind/result.txt b/dupfind/result.txt new file mode 100644 index 0000000..24203de --- /dev/null +++ b/dupfind/result.txt @@ -0,0 +1,225 @@ +/home/jcdkiki/code/pr-2023-3384/Kozmin_Nikita_lb3/src/main.c: [49, 52] duplicates [27, 30] + +... + cnt_chars_sentence++; + sentenses[cnt_sentences-1] = realloc(sentenses[cnt_sentences-1], + sizeof(char)*(cnt_chars_sentence+1)); + sentenses[cnt_sentences-1][cnt_chars_sentence-1] = cur_char; +... + cnt_chars_sentence++; + sentenses[cnt_sentences-1] = realloc(sentenses[cnt_sentences-1], + sizeof(char)*(cnt_chars_sentence+1)); + sentenses[cnt_sentences-1][cnt_chars_sentence-1] = cur_char; +... +/home/jcdkiki/code/pr-2023-3384/Kuzmin_Kirill_lb1/src/main.c: [21, 25] duplicates [10, 14] + +... + int ind = -1; + for (int i = 0; i < n; i++){ + if (arr[i] < 0) { + ind = i; + break; +... + int ind = -1; + for (int i = n-1; i > 0; i--){ + if (arr[i] < 0) { + ind = i; + break; +... +/home/jcdkiki/code/pr-2023-3384/Usikov_Anton_cw/src/main.c: [31, 35] duplicates [21, 24] + +... + T = TextRead(); + DelRepStr(&T); + PrintText(&T); + break; +... + T = TextRead(); + DelRepStr(&T); + PrintText(&T); + PrintUpper(&T); + break; +... +/home/jcdkiki/code/pr-2023-3384/Usikov_Anton_cw/src/main.c: [43, 47] duplicates [21, 24] + +... + T = TextRead(); + DelRepStr(&T); + PrintText(&T); + break; +... + T = TextRead(); + DelRepStr(&T); + RemoveNumText(&T); + PrintText(&T); + break; +... +/home/jcdkiki/code/pr-2023-3384/Berlet_Maxim_cw/src/main.c: [74, 77] duplicates [69, 72] + +... + case 0:{ + print0(strs, counter); + clean_memory(strs, counter); + break; +... + case 1: + colors(strs, &counter); + clean_memory(strs, counter); + break; +... +/home/jcdkiki/code/pr-2023-3384/Rudakov_Aleksandr_lb1/src/main_lb1.c: [30, 33] duplicates [22, 25] + +... + if (first>second){ + return first; + } else{ + return second; +... + if (first abs(input_array[count])) min = input_array[count]; +... +/home/jcdkiki/code/pr-2023-3384/Maksimova_Ekaterina_lb1/src/main.c: [17, 21] duplicates [5, 9] + +... + int i = 0; + int mx = arr[0]; + for(i; i < size; i++) { + if (arr[i] > mx) { + mx = arr[i]; +... + int i = 0; + int mn = arr[0]; + for(i; i < size; i++) { + if(arr[i] < mn) { + mn = arr[i]; +... +/home/jcdkiki/code/pr-2023-3384/Maksimova_Ekaterina_cw/src/main.c: [39, 43] duplicates [17, 20] + +... + text = readText(); + removeEmptySentences(&text); + removeCopies(&text); + printText(text); +... + text = readText(); + removeEmptySentences(&text); + removeCopies(&text); + changeVowels(&text); + printText(text); +... +/home/jcdkiki/code/pr-2023-3384/Maksimova_Ekaterina_cw/src/main.c: [65, 69] duplicates [17, 20] + +... + text = readText(); + removeEmptySentences(&text); + removeCopies(&text); + printText(text); +... + text = readText(); + removeEmptySentences(&text); + removeCopies(&text); + countSymbols(&text); + printText(text); +... +/home/jcdkiki/code/pr-2023-3384/Kozmin_Nikita_cw/src/bananapplesearch.c: [42, 46] duplicates [26, 30] + +... + if (isnewword && !strncmp(&((*sentences)[i][j]), "banana", 6) && + ( (*sentences)[i][j+6]==' ' || (*sentences)[i][j+6]==',' || (*sentences)[i][j+6]=='.' )){ + if (!isprint){ + for (size_t k = 0; k < j; k++){ + printf("%c", (*sentences)[i][k]); +... + else if (isnewword && !strncmp(&((*sentences)[i][j]), "apple", 5) && + ( (*sentences)[i][j+5]==' ' || (*sentences)[i][j+5]==',' || (*sentences)[i][j+5]=='.' )){ + if (!isprint){ + for (size_t k = 0; k < j; k++){ + printf("%c", (*sentences)[i][k]); +... +/home/jcdkiki/code/pr-2023-3384/Kozmin_Nikita_cw/src/preprocessing.c: [29, 34] duplicates [21, 25] + +... + for (size_t i = 0; i < (*cnt_sentences)-1; i++){ + len_fst = strlen((*sentences)[i]); + fst = realloc(fst, sizeof(char)*(len_fst + 1)); + for (size_t k=0; k < (len_fst+1); k++){ + fst[k] = tolower((*sentences)[i][k]); +... + for (size_t j = i+1; j < (*cnt_sentences); j++){ + len_scd = strlen((*sentences)[j]); + if (len_fst == len_scd){ + scd = realloc(scd, sizeof(char)*(len_scd + 1)); + for (size_t k=0; k < (len_scd+1); k++){ + scd[k] = tolower((*sentences)[j][k]); +... +/home/jcdkiki/code/pr-2023-3384/Kozmin_Nikita_cw/src/menu.c: [46, 49] duplicates [32, 35] + +... + case 0: + cnt_sentences = readtext(&sentences); + if (!sentences) return 0; + preprocessing(&sentences, &cnt_sentences); +... + case 2: + cnt_sentences = readtext(&sentences); + if (!sentences) return 0; + preprocessing(&sentences, &cnt_sentences); +... +/home/jcdkiki/code/pr-2023-3384/Kozmin_Nikita_cw/src/menu.c: [61, 64] duplicates [32, 35] + +... + case 0: + cnt_sentences = readtext(&sentences); + if (!sentences) return 0; + preprocessing(&sentences, &cnt_sentences); +... + case 4: + cnt_sentences = readtext(&sentences); + if (!sentences) return 0; + preprocessing(&sentences, &cnt_sentences); +... diff --git a/dupfind/sample.sh b/dupfind/sample.sh new file mode 100755 index 0000000..698bc7d --- /dev/null +++ b/dupfind/sample.sh @@ -0,0 +1,5 @@ +#!/usr/bin/bash +for i in $(find $1 -iname "*.c") +do + dupfind --show $i +done From e06fddb8cbf993fa1ce6230b1a998a182831dcfb Mon Sep 17 00:00:00 2001 From: Gorsky Kirill Date: Wed, 13 Mar 2024 22:36:27 +0300 Subject: [PATCH 2/2] dupfind: add cfg --- dupfind/Makefile | 4 +- dupfind/dupfind | Bin 105728 -> 0 bytes dupfind/main.cpp | 145 ++++++++++++++++++++--------- dupfind/result.txt | 225 --------------------------------------------- dupfind/sample.sh | 2 +- 5 files changed, 107 insertions(+), 269 deletions(-) delete mode 100755 dupfind/dupfind delete mode 100644 dupfind/result.txt diff --git a/dupfind/Makefile b/dupfind/Makefile index 0903494..fefa965 100644 --- a/dupfind/Makefile +++ b/dupfind/Makefile @@ -1,6 +1,6 @@ .PHONY: all install clean uninstall -CC=g++ +CC = g++ all: dupfind @@ -14,4 +14,4 @@ install: dupfind cp dupfind /usr/local/bin uninstall: - rm -f /usr/local/bin/dupfind + rm -f /usr/local/bin/dupfind \ No newline at end of file diff --git a/dupfind/dupfind b/dupfind/dupfind deleted file mode 100755 index 218846a5b965b33c38da291c6b211469e4d99d73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105728 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 diff --git a/dupfind/main.cpp b/dupfind/main.cpp index 76a108e..2b56852 100644 --- a/dupfind/main.cpp +++ b/dupfind/main.cpp @@ -1,36 +1,33 @@ +#include +#include #include #include -#include #include -#include #include -#include #include -#define SEQ_SEARCH_DEPTH 3 -#define SEQ_REPORT_THRESHOLD 4 -#define SIMLARITY_THRESHOLD 0.7 +struct { + bool show = false; + int maxskip = 2; + float similarity_threshold = 0.7f; + int report_len = 4; +} cfg; -struct LineData { +struct linedata_t { std::string str; std::string tab; size_t group_ind; }; -struct GroupData { +struct groupdata_t { std::vector members; const char *color; }; -std::vector lines; +std::vector lines; std::string file_name; -std::unordered_map groups; +std::unordered_map groups; -struct { - bool show = false; -} cfg; - -// trim from end (in place) inline void rtrim(std::string &s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { @@ -38,7 +35,7 @@ inline void rtrim(std::string &s) }).base(), s.end()); } -int strDistance(std::string &a, std::string &b) +int str_distance(std::string &a, std::string &b) { if (a.size() == 0) return b.size(); @@ -62,11 +59,11 @@ int strDistance(std::string &a, std::string &b) return dp.back().back(); } -void assignLineToGroup(int n, float threshold) +void assign_line_to_group(int n, float threshold) { bool ok = false; for (int i = 0; i < n; i++) { - float similarity = 1.f - (float)strDistance(lines[n].str, lines[i].str) / (float)std::max(lines[n].str.size(), lines[i].str.size()); + float similarity = 1.f - (float)str_distance(lines[n].str, lines[i].str) / (float)std::max(lines[n].str.size(), lines[i].str.size()); if (similarity >= threshold) { groups[i].members.push_back(n); @@ -81,37 +78,38 @@ void assignLineToGroup(int n, float threshold) } } -void printLines(int first, int last) +void print_lines(int first, int last) { for (int i = first; i <= last; i++) { std::cout << lines[i].tab << ' ' << lines[i].str << std::endl; } } -void detectSeq(int len, int first, int last) +void report_if_needed(int len, int first, int last) { - if (len >= SEQ_REPORT_THRESHOLD) { + if (len >= cfg.report_len) { std::cout << file_name << ": [" << first+1 << ", " << last+1 << "] duplicates [" << lines[first].group_ind+1 << ", " << lines[last].group_ind+1 << "]\n"; if (cfg.show) { - std::cout << "\n...\n"; - printLines(lines[first].group_ind, lines[last].group_ind); std::cout << "...\n"; - printLines(first, last); + print_lines(lines[first].group_ind, lines[last].group_ind); std::cout << "...\n"; + print_lines(first, last); + std::cout << "...\n\n"; } } } -void findDupSeqs() +void find_sequences() { size_t seq_len = 1; size_t seq_first = 0; size_t seq_last = 0; + for (size_t i = 1; i < lines.size(); i++) { - if (i - seq_last > SEQ_SEARCH_DEPTH) { - detectSeq(seq_len, seq_first, seq_last); + if ((int)(i - seq_last) > cfg.maxskip + 1) { + report_if_needed(seq_len, seq_first, seq_last); seq_len = 1; seq_last = i; seq_first = i; @@ -124,36 +122,100 @@ void findDupSeqs() } } - detectSeq(seq_len, seq_first, seq_last); + report_if_needed(seq_len, seq_first, seq_last); } -bool shouldAssign(int n) +bool is_line_regular(int n) { + if (lines[n].str.size() == 0) + return false; + if (lines[n].str == "}" || lines[n].str == "{") return false; + if (lines[n].str.size() > 0 && lines[n].str[0] == '#') return false; + + if (lines[n].str.size() >= 2 && lines[n].str[0] == '/' && lines[n].str[1] == '/') + return false; + + if (lines[n].str.size() >= 2 && lines[n].str[0] == '/' && lines[n].str[1] == '*') + return false; + + if (lines[n].str.size() >= 6 && lines[n].str.substr(0, 6) == "break;") + return false; + return true; } +void print_help() +{ + std::cout << "Usage: dupfind [options] ...\n" + "options:\n" + " --show show code that was duplicated\n" + " --maxskip X maximum allowed number of lines to skip\n" + " --similarity X similarity threshold (in percent)\n" + " --reportlen X minimal length of sequence to report it\n"; +} + +char **parse_arg(char **argv) +{ + if (strcmp(argv[0], "-h") == 0 || strcmp(argv[0], "--help") == 0) { + print_help(); + exit(0); + } + + if (argv[0][0] != '-' || argv[0][1] != '-') + return argv; + + if (strcmp(argv[0], "--show") == 0) { + cfg.show = true; + return argv + 1; + } + + if (argv[1] == NULL) + return NULL; + + if (strcmp(argv[0], "--maxskip") == 0) { + cfg.maxskip = atoi(argv[1]); + return argv + 2; + } + if (strcmp(argv[0], "--similarity") == 0) { + cfg.similarity_threshold = atof(argv[1]) / 100.f; + return argv + 2; + } + if (strcmp(argv[0], "--reportlen") == 0) { + cfg.report_len = atoi(argv[1]); + return argv + 2; + } + + return argv; +} + int main(int argc, char **argv) { if (argc < 2) { - std::cout << "Usage: code-dup FILENAMES...\n"; - exit(1); + print_help(); + exit(1); } - - for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "--show") == 0) { - cfg.show = true; + + argv++; + while (*argv != NULL) { + char **next = parse_arg(argv); + if (next == NULL) { + std::cout << "Input error\n"; + exit(1); + } + else if (next > argv) { + argv = next; continue; } - + lines.clear(); groups.clear(); - file_name = argv[i]; - std::ifstream file(argv[i]); + file_name = *argv; + std::ifstream file(*argv); if (!file.is_open()) { std::cout << "Failed to open file\n"; exit(1); @@ -173,10 +235,11 @@ int main(int argc, char **argv) file.close(); for (size_t j = 0; j < lines.size(); j++) { - if (shouldAssign(j)) - assignLineToGroup(j, SIMLARITY_THRESHOLD); + if (is_line_regular(j)) + assign_line_to_group(j, cfg.similarity_threshold); } - findDupSeqs(); + find_sequences(); + argv++; } } diff --git a/dupfind/result.txt b/dupfind/result.txt deleted file mode 100644 index 24203de..0000000 --- a/dupfind/result.txt +++ /dev/null @@ -1,225 +0,0 @@ -/home/jcdkiki/code/pr-2023-3384/Kozmin_Nikita_lb3/src/main.c: [49, 52] duplicates [27, 30] - -... - cnt_chars_sentence++; - sentenses[cnt_sentences-1] = realloc(sentenses[cnt_sentences-1], - sizeof(char)*(cnt_chars_sentence+1)); - sentenses[cnt_sentences-1][cnt_chars_sentence-1] = cur_char; -... - cnt_chars_sentence++; - sentenses[cnt_sentences-1] = realloc(sentenses[cnt_sentences-1], - sizeof(char)*(cnt_chars_sentence+1)); - sentenses[cnt_sentences-1][cnt_chars_sentence-1] = cur_char; -... -/home/jcdkiki/code/pr-2023-3384/Kuzmin_Kirill_lb1/src/main.c: [21, 25] duplicates [10, 14] - -... - int ind = -1; - for (int i = 0; i < n; i++){ - if (arr[i] < 0) { - ind = i; - break; -... - int ind = -1; - for (int i = n-1; i > 0; i--){ - if (arr[i] < 0) { - ind = i; - break; -... -/home/jcdkiki/code/pr-2023-3384/Usikov_Anton_cw/src/main.c: [31, 35] duplicates [21, 24] - -... - T = TextRead(); - DelRepStr(&T); - PrintText(&T); - break; -... - T = TextRead(); - DelRepStr(&T); - PrintText(&T); - PrintUpper(&T); - break; -... -/home/jcdkiki/code/pr-2023-3384/Usikov_Anton_cw/src/main.c: [43, 47] duplicates [21, 24] - -... - T = TextRead(); - DelRepStr(&T); - PrintText(&T); - break; -... - T = TextRead(); - DelRepStr(&T); - RemoveNumText(&T); - PrintText(&T); - break; -... -/home/jcdkiki/code/pr-2023-3384/Berlet_Maxim_cw/src/main.c: [74, 77] duplicates [69, 72] - -... - case 0:{ - print0(strs, counter); - clean_memory(strs, counter); - break; -... - case 1: - colors(strs, &counter); - clean_memory(strs, counter); - break; -... -/home/jcdkiki/code/pr-2023-3384/Rudakov_Aleksandr_lb1/src/main_lb1.c: [30, 33] duplicates [22, 25] - -... - if (first>second){ - return first; - } else{ - return second; -... - if (first abs(input_array[count])) min = input_array[count]; -... -/home/jcdkiki/code/pr-2023-3384/Maksimova_Ekaterina_lb1/src/main.c: [17, 21] duplicates [5, 9] - -... - int i = 0; - int mx = arr[0]; - for(i; i < size; i++) { - if (arr[i] > mx) { - mx = arr[i]; -... - int i = 0; - int mn = arr[0]; - for(i; i < size; i++) { - if(arr[i] < mn) { - mn = arr[i]; -... -/home/jcdkiki/code/pr-2023-3384/Maksimova_Ekaterina_cw/src/main.c: [39, 43] duplicates [17, 20] - -... - text = readText(); - removeEmptySentences(&text); - removeCopies(&text); - printText(text); -... - text = readText(); - removeEmptySentences(&text); - removeCopies(&text); - changeVowels(&text); - printText(text); -... -/home/jcdkiki/code/pr-2023-3384/Maksimova_Ekaterina_cw/src/main.c: [65, 69] duplicates [17, 20] - -... - text = readText(); - removeEmptySentences(&text); - removeCopies(&text); - printText(text); -... - text = readText(); - removeEmptySentences(&text); - removeCopies(&text); - countSymbols(&text); - printText(text); -... -/home/jcdkiki/code/pr-2023-3384/Kozmin_Nikita_cw/src/bananapplesearch.c: [42, 46] duplicates [26, 30] - -... - if (isnewword && !strncmp(&((*sentences)[i][j]), "banana", 6) && - ( (*sentences)[i][j+6]==' ' || (*sentences)[i][j+6]==',' || (*sentences)[i][j+6]=='.' )){ - if (!isprint){ - for (size_t k = 0; k < j; k++){ - printf("%c", (*sentences)[i][k]); -... - else if (isnewword && !strncmp(&((*sentences)[i][j]), "apple", 5) && - ( (*sentences)[i][j+5]==' ' || (*sentences)[i][j+5]==',' || (*sentences)[i][j+5]=='.' )){ - if (!isprint){ - for (size_t k = 0; k < j; k++){ - printf("%c", (*sentences)[i][k]); -... -/home/jcdkiki/code/pr-2023-3384/Kozmin_Nikita_cw/src/preprocessing.c: [29, 34] duplicates [21, 25] - -... - for (size_t i = 0; i < (*cnt_sentences)-1; i++){ - len_fst = strlen((*sentences)[i]); - fst = realloc(fst, sizeof(char)*(len_fst + 1)); - for (size_t k=0; k < (len_fst+1); k++){ - fst[k] = tolower((*sentences)[i][k]); -... - for (size_t j = i+1; j < (*cnt_sentences); j++){ - len_scd = strlen((*sentences)[j]); - if (len_fst == len_scd){ - scd = realloc(scd, sizeof(char)*(len_scd + 1)); - for (size_t k=0; k < (len_scd+1); k++){ - scd[k] = tolower((*sentences)[j][k]); -... -/home/jcdkiki/code/pr-2023-3384/Kozmin_Nikita_cw/src/menu.c: [46, 49] duplicates [32, 35] - -... - case 0: - cnt_sentences = readtext(&sentences); - if (!sentences) return 0; - preprocessing(&sentences, &cnt_sentences); -... - case 2: - cnt_sentences = readtext(&sentences); - if (!sentences) return 0; - preprocessing(&sentences, &cnt_sentences); -... -/home/jcdkiki/code/pr-2023-3384/Kozmin_Nikita_cw/src/menu.c: [61, 64] duplicates [32, 35] - -... - case 0: - cnt_sentences = readtext(&sentences); - if (!sentences) return 0; - preprocessing(&sentences, &cnt_sentences); -... - case 4: - cnt_sentences = readtext(&sentences); - if (!sentences) return 0; - preprocessing(&sentences, &cnt_sentences); -... diff --git a/dupfind/sample.sh b/dupfind/sample.sh index 698bc7d..5fd0879 100755 --- a/dupfind/sample.sh +++ b/dupfind/sample.sh @@ -1,5 +1,5 @@ #!/usr/bin/bash for i in $(find $1 -iname "*.c") do - dupfind --show $i + ./dupfind --similarity 90 --show $i done